1
2 /*
3 # Sfront, a SAOL to C translator
4 # This file: Network library -- SIP functions
5 #
6 # Copyright (c) 2000-2006, Regents of the University of California
7 # All rights reserved.
8 #
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions are
11 # met:
12 #
13 # Redistributions of source code must retain the above copyright
14 # notice, this list of conditions and the following disclaimer.
15 #
16 # Redistributions in binary form must reproduce the above copyright
17 # notice, this list of conditions and the following disclaimer in the
18 # documentation and/or other materials provided with the distribution.
19 #
20 # Neither the name of the University of California, Berkeley nor the
21 # names of its contributors may be used to endorse or promote products
22 # derived from this software without specific prior written permission.
23 #
24 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #
36 # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu
37 */
38
39 #ifndef NSYS_NET
40 #include "net_include.h"
41 #endif
42
43 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
44 /* high-level SIP functions */
45 /*______________________________________________________________*/
46
47 /****************************************************************/
48 /* initialize SIP address and INVITE packet */
49 /****************************************************************/
50
nsys_initsip(void)51 int nsys_initsip(void)
52
53 {
54
55 /************************/
56 /* create SIP addresses */
57 /************************/
58
59 if ((nsys_netin_sipaddr(nsys_rtp_fd, NSYS_SIP_IP,
60 NSYS_SIP_RTP_PORT) != NSYS_DONE) ||
61 (nsys_netin_sipaddr(nsys_rtcp_fd, NSYS_SIP_IP,
62 NSYS_SIP_RTCP_PORT) != NSYS_DONE))
63 return NSYS_ERROR;
64
65 nsys_rtp_cseq = nsys_rtcp_cseq = 1;
66
67 /***********************************/
68 /* create SIP packets and send off */
69 /***********************************/
70
71 nsys_createsip(nsys_rtp_fd, "INVITE", nsys_rtp_invite, NULL, NULL);
72 nsys_sendsip(nsys_rtp_fd, NULL, nsys_rtp_invite);
73
74 nsys_createsip(nsys_rtcp_fd, "INVITE", nsys_rtcp_invite, NULL, NULL);
75 nsys_sendsip(nsys_rtcp_fd, NULL, nsys_rtcp_invite);
76
77 nsys_rtp_sipretry = nsys_rtcp_sipretry = 1;
78
79 nsys_behind_nat = 0;
80
81 nsys_createsip(nsys_rtp_fd, "INFO", nsys_rtp_info, NULL, NULL);
82 nsys_createsip(nsys_rtcp_fd, "INFO", nsys_rtcp_info, NULL, NULL);
83
84 return NSYS_DONE;
85 }
86
87 /****************************************************************/
88 /* handle a SIP reply packet */
89 /****************************************************************/
90
nsys_netin_reply(int fd,struct sockaddr_in * addr,unsigned char * packet,unsigned short status)91 void nsys_netin_reply(int fd, struct sockaddr_in * addr,
92 unsigned char * packet, unsigned short status)
93
94 {
95 unsigned char ack[NSYS_UDPMAXSIZE+1];
96 char natline[NSYS_SDPNATSIZE];
97 char nonce[NSYS_BASE64_LENGTH];
98 unsigned long callid, cseq;
99 char * invite;
100
101 /***********************/
102 /* SIP validity checks */
103 /***********************/
104
105 if (nsys_netin_siporigin(fd, addr) == NSYS_ERROR)
106 return;
107
108 if (nsys_netin_replyparse(fd, packet, nonce, natline, &callid, &cseq)
109 == NSYS_ERROR)
110 return;
111
112 /*************************************/
113 /* ignore informational status codes */
114 /*************************************/
115
116 if ((status >= 100) && (status < 200))
117 return;
118
119 /***************************/
120 /* all others receive acks */
121 /***************************/
122
123 nsys_netin_ack(fd, ack, callid, cseq);
124 nsys_sendsip(fd, addr, ack);
125
126 /********************************/
127 /* take no action if unexpected */
128 /********************************/
129
130 if ((fd == nsys_rtp_fd) && ((nsys_rtcp_ex & NSYS_RTCPEX_RTPSIP) == 0))
131 return;
132
133 if ((fd == nsys_rtcp_fd) && ((nsys_rtcp_ex & NSYS_RTCPEX_RTCPSIP) == 0))
134 return;
135
136 /*************************/
137 /* 200 OK --> clear flag */
138 /*************************/
139
140 if ((status >= 200) && (status < 300))
141 {
142 if (fd == nsys_rtp_fd)
143 {
144 nsys_rtcp_ex &= ~(NSYS_RTCPEX_RTPSIP | NSYS_RTCPEX_RTPNEXT);
145 nsys_rtp_authretry = 0;
146
147 if (nsys_rtcp_sipretry)
148 nsys_warning(NSYS_WARN_STANDARD,
149 "SIP server contact successful, awaiting client SIP");
150 nsys_rtp_sipretry = 0;
151 }
152 else
153 {
154 nsys_rtcp_ex &= ~(NSYS_RTCPEX_RTCPSIP | NSYS_RTCPEX_RTCPNEXT);
155 nsys_rtcp_authretry = 0;
156
157 if (nsys_rtp_sipretry)
158 nsys_warning(NSYS_WARN_STANDARD,
159 "SIP server contact successful, awaiting client SIP");
160
161 nsys_rtcp_sipretry = 0;
162 }
163 return;
164 }
165
166 /************************/
167 /* 401 -- resend INVITE */
168 /************************/
169
170 if ((status == 401) && (nonce[0]))
171 {
172 if (((fd == nsys_rtp_fd) &&
173 (nsys_rtp_authretry++ > NSYS_SIP_AUTHRETRYMAX)) ||
174 ((fd == nsys_rtcp_fd) &&
175 (nsys_rtcp_authretry++ > NSYS_SIP_AUTHRETRYMAX)))
176 {
177 nsys_terminate_error("Initial SIP server authentication failure");
178 return;
179 }
180
181 if (fd == nsys_rtp_fd)
182 {
183 nsys_rtp_cseq++;
184 invite = (char *) nsys_rtp_invite;
185
186 nsys_rtcp_ex |= NSYS_RTCPEX_RTPSIP;
187
188 if (nsys_nexttime < (time(NULL) + NSYS_RTCPTIME_SKIP))
189 nsys_rtcp_ex |= NSYS_RTCPEX_RTPNEXT;
190 else
191 nsys_rtcp_ex &= ~NSYS_RTCPEX_RTPNEXT;
192
193 nsys_createsip(nsys_rtp_fd, "INFO", nsys_rtp_info, NULL, NULL);
194 }
195 else
196 {
197 nsys_rtcp_cseq++;
198 invite = (char *) nsys_rtcp_invite;
199
200 nsys_rtcp_ex |= NSYS_RTCPEX_RTCPSIP;
201
202 if (nsys_nexttime < (time(NULL) + NSYS_RTCPTIME_SKIP))
203 nsys_rtcp_ex |= NSYS_RTCPEX_RTCPNEXT;
204 else
205 nsys_rtcp_ex &= ~NSYS_RTCPEX_RTCPNEXT;
206
207 nsys_createsip(nsys_rtcp_fd, "INFO", nsys_rtcp_info, NULL, NULL);
208 }
209
210 nsys_createsip(fd, "INVITE", (unsigned char *) invite,
211 natline[0] ? natline : NULL, nonce[0] ? nonce : NULL);
212 nsys_sendsip(fd, NULL, (unsigned char *) invite);
213
214 return;
215 }
216
217 /******************************/
218 /* 300 series --> do redirect */
219 /******************************/
220
221 if ((status >= 300) && (status < 400))
222 {
223 nsys_netin_redirect(fd, packet, status);
224 return;
225 }
226
227 /*******************************/
228 /* 400 series --> buggy client */
229 /*******************************/
230
231 if ((status >= 400) && (status < 500))
232 {
233 nsys_warning(NSYS_WARN_STANDARD, APPNAME "/" APPVERSION
234 " is too out-of-date to function with SIP server");
235
236 nsys_warning(NSYS_WARN_STANDARD,
237 "Download new version at:"
238 " http://www.cs.berkeley.edu/~lazzaro/sa/index.html");
239
240 nsys_rtcp_ex &= ~(NSYS_RTCPEX_RTPSIP | NSYS_RTCPEX_RTCPSIP |
241 NSYS_RTCPEX_RTPNEXT | NSYS_RTCPEX_RTCPNEXT);
242
243 nsys_graceful_exit = 1;
244 return;
245 }
246
247 /**********************************/
248 /* 500/600 series --> server down */
249 /**********************************/
250
251 if ((status >= 500) && (status < 700))
252 {
253 nsys_warning(NSYS_WARN_STANDARD,
254 "SIP server is overloaded, refusing new sessions");
255 nsys_warning(NSYS_WARN_STANDARD,
256 "Please try again later. Ending session");
257
258 nsys_rtcp_ex &= ~(NSYS_RTCPEX_RTPSIP | NSYS_RTCPEX_RTCPSIP |
259 NSYS_RTCPEX_RTPNEXT | NSYS_RTCPEX_RTCPNEXT);
260
261 nsys_graceful_exit = 1;
262 return;
263 }
264
265 }
266
267
268 /****************************************************************/
269 /* handle a SIP INVITE packet */
270 /****************************************************************/
271
nsys_netin_invite(int fd,struct sockaddr_in * addr,unsigned char * packet)272 void nsys_netin_invite(int fd, struct sockaddr_in * addr,
273 unsigned char * packet)
274
275 {
276 struct sockaddr_in ** aptr;
277 struct nsys_source * sptr;
278 char line[NSYS_UDPMAXSIZE+1];
279 char media[NSYS_UDPMAXSIZE+1];
280 char sname[NSYS_BASE64_LENGTH];
281 char tool[32] = "unknown";
282 struct nsys_payinfo * marray;
283 int mlen = 0;
284 char cname[32];
285 char dnsname[64];
286 char ip[16], nat_ip[16];
287 unsigned long ssrc, sdp_time, now;
288 unsigned short port, nat_port, ptype;
289 int state, len;
290 int has_nat, has_session, has_time, has_ssrc;
291 int has_dnsname, has_port, has_ip, has_map;
292
293 /*****************************************************************/
294 /* do weak and strong security checks, leave function if failure */
295 /*****************************************************************/
296
297 if (nsys_netin_siporigin(fd, addr) == NSYS_ERROR)
298 return;
299
300 if ((packet = nsys_netin_readmethod(fd, addr, packet)) == NULL)
301 return;
302
303 /*************/
304 /* parse SDP */
305 /*************/
306
307 has_nat = has_session = has_time = has_ssrc = 0;
308 has_dnsname = has_port = has_ip = has_map = 0;
309 state = NSYS_NETIN_SDPSTATE;
310
311 while (state == NSYS_NETIN_SDPSTATE)
312 {
313 len = sscanf((char *) packet, "%1023[^\n]\n", line);
314 if (len && (len != EOF))
315 {
316 switch (line[0]) {
317 case 'v':
318 break;
319 case 's':
320 if ((sscanf(line, "s = %24s", sname) != 1) ||
321 (strcmp((char *) nsys_session_base64, sname)))
322 state = NSYS_NETIN_ERRSTATE;
323 else
324 has_session = 1;
325 break;
326 case 't':
327 if (sscanf(line, "t = %lu", &sdp_time) == 1)
328 {
329 now = time(NULL);
330 sdp_time -= 2208988800UL;
331 has_time = 1;
332
333 if (!nsys_msession || nsys_msessionmirror)
334 {
335 if ((sdp_time > now) &&
336 ((sdp_time - now) > NSYS_MAXLATETIME))
337 state = NSYS_NETIN_ERRSTATE;
338 if ((sdp_time < now) &&
339 ((now-sdp_time) > NSYS_MAXSSESIONTIME))
340 state = NSYS_NETIN_ERRSTATE;
341 }
342 }
343 break;
344 case 'o':
345 if (sscanf(line, "o = %31s %lu %*u IN IP4 %63s",
346 cname, &ssrc, dnsname) != 3)
347 state = NSYS_NETIN_ERRSTATE;
348 else
349 has_dnsname = has_ssrc = 1;
350 break;
351 case 'm':
352 if (sscanf(line, "m = audio %hu RTP/AVP %[0-9 ]", &port, media) != 2)
353 state = NSYS_NETIN_ERRSTATE;
354 else
355 {
356 has_port = 1;
357 if ((mlen = nsys_netin_make_marray(&marray, media)) < 1)
358 state = NSYS_NETIN_ERRSTATE;
359 }
360 break;
361 case 'c':
362 if ((sscanf(line, "c = IN IP4 %15s", ip) != 1) ||
363 !(strcmp(ip, "127.0.0.1") &&
364 strcmp(ip, "0.0.0.0") &&
365 strcmp(ip, "255.255.255.255")))
366 state = NSYS_NETIN_ERRSTATE;
367 else
368 has_ip = 1;
369 break;
370 case 'a':
371 if (sscanf(line, "a = nat : %15s %hu", nat_ip, &nat_port) == 2)
372 {
373 has_nat = strcmp(nat_ip, "127.0.0.1") &&
374 strcmp(nat_ip, "0.0.0.0") &&
375 strcmp(nat_ip, "255.255.255.255");
376 break;
377 }
378 if (sscanf(line, "a = tool : %31[^\n]", tool) == 1)
379 break;
380 if (sscanf(line, "a = rtpmap : %hu", &ptype) == 1)
381 {
382 if ((!mlen) || (!nsys_netin_set_marray(line, marray, mlen)))
383 state = NSYS_NETIN_ERRSTATE;
384 else
385 has_map = 1;
386 break;
387 }
388 break;
389 }
390 packet += strlen(line) + 1;
391 }
392 else
393 state = NSYS_NETIN_EOFSTATE;
394 }
395
396 /****************************************/
397 /* miscellaneous security/syntax checks */
398 /****************************************/
399
400 if (!(has_session && has_time && has_ssrc && has_dnsname
401 && has_port && has_ip && has_map))
402 state = NSYS_NETIN_ERRSTATE;
403
404 if ((strcmp(ip, nsys_clientip) == 0) && (strcmp(cname, nsys_username) == 0)
405 && (port == nsys_rtp_port) && (nsys_myssrc == ssrc))
406 state = NSYS_NETIN_ERRSTATE;
407
408 if (nsys_msession && !nsys_msessionmirror &&
409 ((strcmp(nsys_sip_rtp_ip, ip) && (fd == nsys_rtp_fd)) ||
410 (strcmp(nsys_sip_rtcp_ip, ip) && (fd == nsys_rtcp_fd)) || has_nat ))
411 state = NSYS_NETIN_ERRSTATE;
412
413 if (state == NSYS_NETIN_EOFSTATE)
414 {
415 sptr = nsys_ssrc[ssrc & NSYS_HASHMASK];
416
417 while (sptr && (sptr->ssrc != ssrc))
418 sptr = sptr->xtra;
419
420 if ((sptr == NULL) && nsys_netin_noreplay(ip, port, sdp_time) &&
421 nsys_netin_payvalid(marray, mlen, fd) &&
422 (sptr = nsys_netin_addsrc(fd, ssrc, ip, port)))
423 {
424
425 sptr->siptime = sdp_time;
426 nsys_netin_payset(sptr, marray, mlen);
427 sptr->last_hiseq_ext = nsys_netout_jsend_checkpoint_seqnum;
428
429 if (nsys_msessionmirror)
430 nsys_rtcp_ex &= ~NSYS_RTCPEX_SRCDUPL;
431
432 sptr->cname = calloc(strlen(cname) + strlen(dnsname) + 8,
433 sizeof(char));
434 sprintf(sptr->cname, "%s@%s:%hu", cname, dnsname, port);
435 nsys_status(sptr, "SIP INVITE accepted from");
436 }
437
438 if (sptr && has_nat)
439 {
440 if (fd == nsys_rtp_fd)
441 aptr = &(sptr->alt_rtp_addr);
442 else
443 aptr = &(sptr->alt_rtcp_addr);
444
445 if (*aptr == NULL)
446 {
447 *aptr = calloc(1, sizeof(struct sockaddr_in));
448 (*aptr)->sin_family = AF_INET;
449 }
450 (*aptr)->sin_port = htons(nat_port);
451 (*aptr)->sin_addr.s_addr = inet_addr(nat_ip);
452 }
453 }
454
455 if (state == NSYS_NETIN_ERRSTATE)
456 {
457 sprintf(line, "Discarding a SIP INVITE: probably a client/server bug");
458 nsys_warning(NSYS_WARN_UNUSUAL, line);
459 }
460
461 }
462
463 /****************************************************************/
464 /* close down SIP server connection */
465 /****************************************************************/
466
nsys_sip_shutdown(void)467 void nsys_sip_shutdown(void)
468
469 {
470 unsigned char packet[NSYS_UDPMAXSIZE+1];
471 fd_set set;
472 int rtp_flags, rtcp_flags;
473 struct timeval timeout, deadline;
474 int rtp_send = 1;
475 int rtcp_send = 1;
476 int waitcycles = 0;
477
478 /**********************/
479 /* create BYE packets */
480 /**********************/
481
482 nsys_rtp_cseq++;
483 nsys_rtcp_cseq++;
484
485 nsys_createsip(nsys_rtp_fd, "BYE", nsys_rtp_invite, NULL, NULL);
486 nsys_createsip(nsys_rtcp_fd, "BYE", nsys_rtcp_invite, NULL, NULL);
487
488 /*************************/
489 /* make sockets blocking */
490 /*************************/
491
492 rtp_flags = fcntl(nsys_rtp_fd, F_GETFL);
493 rtcp_flags = fcntl(nsys_rtcp_fd, F_GETFL);
494
495 fcntl(nsys_rtp_fd, F_SETFL, (~O_NONBLOCK) & rtp_flags );
496 fcntl(nsys_rtcp_fd, F_SETFL, (~O_NONBLOCK) & rtcp_flags);
497
498 /***********************************/
499 /* do three sends before giving up */
500 /***********************************/
501
502 while ((waitcycles++ < 3) && (rtp_send || rtcp_send))
503 {
504
505 if (rtp_send)
506 nsys_sendsip(nsys_rtp_fd, NULL, nsys_rtp_invite);
507 if (rtcp_send)
508 nsys_sendsip(nsys_rtcp_fd, NULL, nsys_rtcp_invite);
509
510 /* one second between resends */
511
512 gettimeofday(&deadline, NULL);
513 deadline.tv_sec++;
514
515 do {
516
517 FD_ZERO(&set);
518 FD_SET(nsys_rtp_fd, &set);
519 FD_SET(nsys_rtcp_fd, &set);
520
521 timeout.tv_sec = 0;
522 timeout.tv_usec = 200000;
523
524 select(nsys_max_fd, &set, NULL, NULL, &timeout);
525
526 if (FD_ISSET(nsys_rtp_fd, &set) &&
527 (recv(nsys_rtp_fd, packet, NSYS_UDPMAXSIZE, 0) > 0) &&
528 (packet[NSYS_RTPLOC_BYTE1] == 'S'))
529 rtp_send = 0;
530
531 if (FD_ISSET(nsys_rtcp_fd, &set) &&
532 (recv(nsys_rtcp_fd, packet, NSYS_UDPMAXSIZE, 0) > 0) &&
533 (packet[NSYS_RTPLOC_BYTE1] == 'S'))
534 rtcp_send = 0;
535
536 gettimeofday(&timeout, NULL);
537
538 } while ((rtcp_send | rtp_send) &&
539 ((timeout.tv_sec < deadline.tv_sec) ||
540 ((timeout.tv_sec == deadline.tv_sec) &&
541 (timeout.tv_usec < deadline.tv_usec))));
542
543 }
544
545 /*************************/
546 /* restore socket status */
547 /*************************/
548
549 fcntl(nsys_rtp_fd, F_SETFL, rtp_flags);
550 fcntl(nsys_rtcp_fd, F_SETFL, rtcp_flags);
551
552 }
553
554
555 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
556 /* low-level SIP functions */
557 /*______________________________________________________________*/
558
559
560 /****************************************************************/
561 /* create a SIP method packet */
562 /****************************************************************/
563
nsys_createsip(int fd,char * method,unsigned char * sip,char * natline,char * nonce)564 void nsys_createsip(int fd, char * method, unsigned char * sip,
565 char * natline, char * nonce)
566
567 {
568 unsigned char base64_digest[NSYS_BASE64_LENGTH];
569 unsigned char binary_digest[NSYS_MD5_LENGTH];
570 char media[4*NSYS_RTP_PAYSIZE + 1];
571 char nline[16+NSYS_BASE64_LENGTH];
572 int i, j, len, body, dpoint;
573
574
575 /**********************/
576 /* create SIP headers */
577 /**********************/
578
579 body = snprintf((char *) sip, NSYS_UDPMAXSIZE+1,
580 "%s sip:%s@%s:%hu SIP/2.0\n" /* INVITE or BYE method */
581 "i: %lu\n" /* Call-ID */
582 "v: SIP/2.0/UDP %s:%hu\n" /* Via */
583 "%s" /* Content-Type */
584 "f: sip:%s@%s\n" /* From */
585 "t: sip:%s@%s:%hu\n" /* To */
586 "CSeq: %lu\n" /* CSeq */
587 "User-Agent: %s/%s\n", /* User-Agent */
588
589 /* SIP URL */
590
591 method, nsys_session_base64,
592 (fd == nsys_rtp_fd) ? nsys_sip_rtp_ip : nsys_sip_rtcp_ip,
593 (fd == nsys_rtp_fd) ? nsys_sip_rtp_port : nsys_sip_rtcp_port,
594
595 /* Call-ID */
596
597 nsys_myssrc + (fd == nsys_rtcp_fd),
598
599 /* Via */
600
601 nsys_clientip,
602 (fd == nsys_rtp_fd) ? nsys_rtp_port : nsys_rtcp_port,
603
604 /* Content-Type */
605
606 (method[2] == 'V') ? "c: application/sdp\n" : "",
607
608 /* From */
609
610 nsys_username, nsys_clientname,
611
612 /* To */
613
614 nsys_session_base64,
615 (fd == nsys_rtp_fd) ? nsys_sip_rtp_ip : nsys_sip_rtcp_ip,
616 (fd == nsys_rtp_fd) ? nsys_sip_rtp_port : nsys_sip_rtcp_port,
617
618 /* CSeq */
619
620 (fd == nsys_rtp_fd) ? nsys_rtp_cseq : nsys_rtcp_cseq,
621
622 /* User-Agent */
623
624 APPNAME, APPVERSION
625
626 );
627
628 if (body > NSYS_UDPMAXSIZE)
629 NSYS_ERROR_TERMINATE("SIP INVITE packet creation error [1]");
630
631 if (method[2] != 'V') /* BYE/INFO currently have no body */
632 return;
633
634 /*********************/
635 /* add Authorization */
636 /*********************/
637
638 if (nonce)
639 {
640 body += snprintf((char *) &(sip[body]), NSYS_UDPMAXSIZE+1-body,
641 "Authorization: SignSDP nonce=\"%s\", "
642 "digest=\"012345678901234567890A==\"\n",
643 nonce);
644 sprintf(nline, "a=nonce:\"%s\"\n", nonce);
645 dpoint = body - 26;
646 }
647 else
648 dpoint = 0;
649
650 if (body > NSYS_UDPMAXSIZE)
651 NSYS_ERROR_TERMINATE("SIP INVITE packet creation error [2]");
652
653 /***********/
654 /* add SDP */
655 /***********/
656
657 for (j = i = 0; i < NSYS_RTP_PAYSIZE; i++)
658 j += sprintf(&(media[j]), "%hhu ", nsys_payload_types[i].ptype);
659
660 len = body + snprintf((char *) &(sip[body]), NSYS_UDPMAXSIZE+1-body,
661 "\n"
662 "v=0\n"
663 "o=%s %lu 0 IN IP4 %s\n" /* CNAME, SSRC, IP */
664 "s=%s\n" /* sessionname */
665 "a=tool:%s %s\n" /* SDP creator */
666 "t=%lu 0\n" /* current time */
667 "m=audio %i RTP/AVP %s\n" /* media */
668 "c=IN IP4 %s\n" /* ipnumber */
669 "%s" /* nonce, if needed */
670 "%s", /* nat, if needed */
671
672 /* SDP originator (o=) */
673
674 nsys_username, nsys_myssrc, nsys_clientname,
675
676 /* SDP session (s=) */
677
678 nsys_session_base64,
679
680 /* SDP tool (a=tool) */
681
682 APPNAME, APPVERSION,
683
684 /* NTP time */
685
686 ((unsigned long) time(NULL)) + NSYS_SIP_UNIXTONTP,
687
688 /* SDP media (m=) */
689
690 nsys_rtp_port, media,
691
692 /* SDP connection (c=) */
693
694 nsys_clientip,
695
696 /* nonce line */
697
698 nonce ? nline : "",
699
700 /* nat line */
701
702 natline ? natline : ""
703
704 );
705
706 if (len > NSYS_UDPMAXSIZE)
707 NSYS_ERROR_TERMINATE("SIP INVITE packet creation error [3]");
708
709 for (i = 0; i < NSYS_RTP_PAYSIZE; i++)
710 {
711 /**********************/
712 /* append rtpmap line */
713 /**********************/
714
715 len += snprintf((char *) &(sip[len]), NSYS_UDPMAXSIZE+1 - len,
716 "a=rtpmap:%hhu %s/%i\n",
717 nsys_payload_types[i].ptype,
718 nsys_payload_types[i].name,
719 nsys_payload_types[i].srate);
720
721 if ((len > NSYS_UDPMAXSIZE))
722 NSYS_ERROR_TERMINATE("SIP INVITE packet creation error [4]");
723
724 /*********************/
725 /* append fmtp lines */
726 /*********************/
727
728 switch (nsys_payload_types[i].pindex) {
729 case NSYS_MPEG4_PINDEX:
730 len += snprintf((char *) &(sip[len]), NSYS_UDPMAXSIZE+1 - len,
731
732 "a=fmtp:%hhu streamtype=5; mode=rtp-midi; profile-level-id=12;"
733 " config=\"\"; render=synthetic; subrender=default; rinit=audio/asc;"
734 " tsmode=buffer; octpos=last; mperiod=%lu;"
735 " rtp_ptime=0; rtp_maxptime=0; cm_unused=DEFMQVX;%s"
736 " guardtime=%lu\n",
737
738 nsys_payload_types[i].ptype,
739
740 /* tsmode line */
741
742 (unsigned long) EV(ACYCLE),
743
744 /* rtp_ptime line */
745
746 (nsys_feclevel != NSYS_SM_FEC_NONE)
747 ? "" : " j_sec=none;",
748
749 /* guardtime line */
750
751 (unsigned long)(NSYS_SM_GUARD_MAXTIME*EV(ARATE) + 0.5F)
752
753 );
754
755 if ((len > NSYS_UDPMAXSIZE))
756 NSYS_ERROR_TERMINATE("SIP INVITE packet creation error [5]");
757 break;
758 default:
759 break;
760 }
761
762 }
763
764 /***************************************/
765 /* compute digest, place in SIP header */
766 /***************************************/
767
768 if (nonce)
769 {
770 nsys_hmac_md5(&(sip[body + 1]), len - body - 1,
771 nsys_keydigest, binary_digest);
772 nsys_digest_base64(base64_digest, binary_digest);
773 for (i = 0; i < NSYS_BASE64_LENGTH - 1; i++)
774 sip[dpoint + i] = base64_digest[i];
775 }
776 }
777
778 /****************************************************************/
779 /* reads an INVITE, generates an OK */
780 /****************************************************************/
781
nsys_netin_readmethod(int fd,struct sockaddr_in * addr,unsigned char * packet)782 unsigned char * nsys_netin_readmethod(int fd, struct sockaddr_in * addr,
783 unsigned char * packet)
784
785 {
786 unsigned char local_base64[NSYS_BASE64_LENGTH];
787 unsigned char reply[NSYS_UDPMAXSIZE+1];
788 unsigned char line[NSYS_UDPMAXSIZE+1];
789 unsigned char nonce[NSYS_BASE64_LENGTH];
790 unsigned char digest[NSYS_BASE64_LENGTH];
791 unsigned char local_binary[NSYS_MD5_LENGTH];
792 unsigned char text[14];
793 unsigned char * ret;
794 int found_invite, found_callid, found_reply, found_auth;
795 int num, len, first, overflow;
796 unsigned long callid, inreplyto;
797
798 first = 1;
799 overflow = len = found_invite = found_callid = found_reply = found_auth = 0;
800 nonce[0] = digest[0] = '\0';
801
802 /***********************************************************/
803 /* extract Call-ID, In-Reply-To, Nonce and Digest from SIP */
804 /***********************************************************/
805
806 while ((num = sscanf((char *) packet, "%[^\n]\n", line)) && (num != EOF))
807 {
808 if (first)
809 {
810 first = 0;
811 found_invite = (line == ((unsigned char *)strstr((char *)line,"INVITE")));
812
813 if ((len += strlen("SIP/2.0 200\n")) < NSYS_UDPMAXSIZE+1)
814 strcpy((char *) reply, "SIP/2.0 200\n");
815 else
816 overflow = 1;
817 }
818 else
819 {
820 if ((len += strlen((char *) line) + 1) < NSYS_UDPMAXSIZE+1)
821 {
822 strcat((char *) reply, (char *) line);
823 strcat((char *) reply, "\n");
824 }
825 else
826 overflow = 1;
827
828 if ((line[0] == 'i') || (line[0] == 'C'))
829 found_callid |= ((sscanf((char *) line, "i : %lu", &callid) == 1) ||
830 (sscanf((char *) line, "Call-ID : %lu", &callid) == 1));
831 if (line[0] == 'I')
832 found_reply |= (sscanf((char *) line, "In-Reply-To : %lu",&inreplyto) == 1);
833
834 if (line[0] == 'A')
835 found_auth |= ((sscanf((char *) line, "Authorization : SignSDP "
836 "nonce = \"%24[^\"]\" , "
837 "digest = \"%24[^\"]\" , ",
838 nonce, digest) == 2) ||
839 (sscanf((char *) line, "Authorization : SignSDP "
840 "digest = \"%24[^\"]\" , "
841 "nonce = \"%24[^\"]\" , ",
842 digest, nonce) == 2));
843 }
844 packet += strlen((char *) line) + 1;
845 }
846
847 ret = (num != EOF) ? packet + 1 : NULL;
848
849 if (found_invite && found_callid && found_reply &&
850 (inreplyto == (nsys_myssrc + (fd == nsys_rtcp_fd))))
851 {
852 memcpy(&(text[0]), &callid, 4);
853 memcpy(&(text[4]), &inreplyto, 4);
854 memcpy(&(text[8]), &(addr->sin_addr), 4);
855 memcpy(&(text[12]), &(addr->sin_port), 2);
856
857 nsys_hmac_md5(text, 14, nsys_keydigest, local_binary);
858 nsys_digest_base64(local_base64, local_binary);
859
860 if ((!found_auth) || strcmp((char *) local_base64, (char *) nonce))
861 {
862 sprintf((char *) line, "WWW-Authenticate: SignSDP nonce =\"%s\"\n",
863 local_base64);
864
865 if ((len += strlen((char *)line)) < NSYS_UDPMAXSIZE+1)
866 strcat((char *) reply, (char *) line);
867 else
868 overflow = 1;
869
870 reply[8] = '4'; reply[10] = '1'; /* 200 -> 401 */
871 ret = NULL;
872 }
873 }
874 else
875 ret = NULL;
876
877 if (ret && (nsys_msession == 0))
878 {
879 nsys_hmac_md5(ret, strlen((char *) ret), nsys_keydigest, local_binary);
880 nsys_digest_base64(local_base64, local_binary);
881 if (strcmp((char *) digest, (char *) local_base64))
882 ret = NULL;
883 }
884
885 nsys_sendsip(fd, NULL, reply);
886
887 if (!ret && found_auth)
888 nsys_warning(NSYS_WARN_UNUSUAL,
889 "Discarding a SIP INVITE: probably a client/server bug");
890
891 if (overflow)
892 nsys_warning(NSYS_WARN_UNUSUAL,
893 "Send a truncated 200 or 401: probably a client/server bug");
894
895 return ret;
896 }
897
898
899 /****************************************************************/
900 /* reads a final response, generate an ACK */
901 /****************************************************************/
902
nsys_netin_ack(int fd,unsigned char * reply,unsigned long callid,unsigned long cseq)903 void nsys_netin_ack(int fd, unsigned char * reply,
904 unsigned long callid, unsigned long cseq)
905
906 {
907 int len;
908
909 /****************************/
910 /* create top of ACK header */
911 /****************************/
912
913 len = snprintf((char *) reply, NSYS_UDPMAXSIZE+1,
914
915 "ACK sip:%s@%s:%hu SIP/2.0\n"
916 "v: SIP/2.0/UDP %s:%hu\n" /* Via */
917 "f: sip:%s@%s\n" /* From */
918 "t: sip:%s@%s:%hu\n" /* To */
919 "i: %lu\n" /* Call-ID */
920 "CSeq: %lu\n" /* CSeq */
921 "User-Agent: %s/%s\n", /* User-Agent */
922
923 /* method line */
924
925 nsys_session_base64,
926 (fd == nsys_rtp_fd) ? nsys_sip_rtp_ip : nsys_sip_rtcp_ip,
927 (fd == nsys_rtp_fd) ? nsys_sip_rtp_port : nsys_sip_rtcp_port,
928
929 /* Via */
930
931 nsys_clientip,
932 (fd == nsys_rtp_fd) ? nsys_rtp_port : nsys_rtcp_port,
933
934 /* From */
935
936 nsys_username, nsys_clientname,
937
938 /* To */
939
940 nsys_session_base64,
941 (fd == nsys_rtp_fd) ? nsys_sip_rtp_ip : nsys_sip_rtcp_ip,
942 (fd == nsys_rtp_fd) ? nsys_sip_rtp_port : nsys_sip_rtcp_port,
943
944 /* Call-ID, CSeq */
945
946 callid, cseq,
947
948 /* User-Agent */
949
950 APPNAME, APPVERSION
951
952 );
953
954 if (len > NSYS_UDPMAXSIZE)
955 NSYS_ERROR_TERMINATE("SIP REPLY packet creation error [1]");
956
957 }
958
959 /****************************************************************/
960 /* read a SIP/2.0 reply packet, parse useful fields */
961 /****************************************************************/
962
nsys_netin_replyparse(int fd,unsigned char * packet,char * nonce,char * natline,unsigned long * callid,unsigned long * cseq)963 int nsys_netin_replyparse(int fd, unsigned char * packet,
964 char * nonce, char * natline,
965 unsigned long * callid, unsigned long * cseq)
966
967 {
968 char line[NSYS_UDPMAXSIZE+1];
969 unsigned short nat_port;
970 unsigned char nat_ip[16];
971 int found_callid = 0;
972 int found_cseq = 0;
973 int found_auth = 0;
974
975 natline[0] = '\0';
976 nonce[0] = '\0';
977
978 while (sscanf((char *) packet,"%[^\n]\n",line) == 1)
979 {
980 packet += strlen(line) + 1;
981
982 if ((sscanf(line, "i : %lu", callid) == 1) ||
983 (sscanf(line, "Call-ID : %lu", callid) == 1))
984 {
985 if (found_callid || (*callid != (nsys_myssrc + (fd == nsys_rtcp_fd))))
986 return NSYS_ERROR;
987 found_callid = 1;
988 }
989
990 if ((sscanf(line, "CSeq : %lu", cseq) == 1))
991 {
992 if (found_cseq)
993 return NSYS_ERROR;
994 found_cseq = 1;
995 }
996
997 if (sscanf(line,
998 "WWW-Authenticate : SignSDP nonce = \"%24[^\"]\"",
999 nonce) == 1)
1000 {
1001 if (found_auth || !nsys_digest_syntaxcheck(nonce))
1002 nonce[0] = '\0';
1003 else
1004 found_auth = 1;
1005 }
1006
1007 if ((sscanf(line, "v : %*[^;]; received = %15[0-9.] ; rport = %hu ",
1008 nat_ip, &nat_port) == 2) ||
1009 (sscanf(line, "Via : %*[^;]; received = %15[0-9.] ; rport = %hu ",
1010 nat_ip, &nat_port) == 2))
1011 {
1012 sprintf(natline, "a=nat:%s %hu\n", nat_ip, nat_port);
1013 nsys_behind_nat = 1;
1014 }
1015 }
1016
1017 return ((found_callid && found_cseq) ? NSYS_DONE : NSYS_ERROR);
1018 }
1019
1020 /****************************************************************/
1021 /* read a SIP/2.0 300-series packet, do redirection */
1022 /****************************************************************/
1023
nsys_netin_redirect(int fd,unsigned char * packet,unsigned short status)1024 void nsys_netin_redirect(int fd, unsigned char * packet,
1025 unsigned short status)
1026
1027 {
1028 char line[NSYS_UDPMAXSIZE+1];
1029 int found = 0;
1030 char ip[16];
1031 unsigned short port;
1032 char * invite;
1033
1034 /* find first contact address, extract IP and port */
1035
1036 while (sscanf((char *) packet,"%[^\n]\n",line) == 1)
1037 {
1038 packet += strlen(line) + 1;
1039 if ((found = (sscanf(line,"m:%*[^@]@%15[^:]:%hu", ip, &port) == 2)))
1040 break;
1041 if ((found = (sscanf(line,
1042 "Contact:%*[^@]@%15[^:]:%hu", ip, &port) == 2)))
1043 break;
1044 }
1045
1046 /* handle incomplete redirect packets */
1047
1048 if ((!found) || (nsys_netin_sipaddr(fd, ip, port) != NSYS_DONE))
1049 {
1050 nsys_terminate_error("SIP redirection to an unavailable/unknown server");
1051
1052 nsys_rtcp_ex &= ~(NSYS_RTCPEX_RTPSIP | NSYS_RTCPEX_RTCPSIP |
1053 NSYS_RTCPEX_RTPNEXT | NSYS_RTCPEX_RTCPNEXT);
1054 return;
1055 }
1056
1057 /* send INVITE to new server */
1058
1059 nsys_stderr_size +=
1060 fprintf(stderr, "Redirecting %s INVITE to %s:%hu, please stand by ...\n",
1061 fd == nsys_rtp_fd ? "RTP" : "RTCP", ip, port);
1062 fflush(stderr);
1063
1064 if (fd == nsys_rtp_fd)
1065 {
1066 invite = (char *) nsys_rtp_invite;
1067
1068 nsys_rtcp_ex &= ~NSYS_RTCPEX_RTPNEXT;
1069 nsys_rtcp_ex |= NSYS_RTCPEX_RTPSIP;
1070 nsys_rtp_authretry = 0;
1071 nsys_createsip(nsys_rtp_fd, "INFO", nsys_rtp_info, NULL, NULL);
1072 }
1073 else
1074 {
1075 invite = (char *) nsys_rtcp_invite;
1076
1077 nsys_rtcp_ex &= ~NSYS_RTCPEX_RTCPNEXT;
1078 nsys_rtcp_ex |= NSYS_RTCPEX_RTCPSIP;
1079 nsys_rtcp_authretry = 0;
1080 nsys_createsip(nsys_rtcp_fd, "INFO", nsys_rtcp_info, NULL, NULL);
1081 }
1082
1083 nsys_createsip(fd, "INVITE", (unsigned char *) invite, NULL, NULL);
1084 nsys_sendsip(fd, NULL, (unsigned char *) invite);
1085
1086 }
1087
1088 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1089 /* utility SIP functions */
1090 /*______________________________________________________________*/
1091
1092 /****************************************************************/
1093 /* send a formatted SIP packet */
1094 /****************************************************************/
1095
nsys_sendsip(int fd,struct sockaddr_in * addr,unsigned char * sip)1096 void nsys_sendsip(int fd, struct sockaddr_in * addr, unsigned char * sip)
1097
1098 {
1099 int retry = 0;
1100
1101 if (addr == NULL)
1102 addr = (fd == nsys_rtp_fd) ? &nsys_sip_rtp_addr : &nsys_sip_rtcp_addr;
1103
1104 while (sendto(fd, sip, strlen((char *) sip) + 1, 0, (struct sockaddr *) addr,
1105 sizeof(struct sockaddr)) == -1)
1106 {
1107 if (errno == EAGAIN)
1108 continue;
1109
1110 if ((errno == EINTR) || (errno == ENOBUFS))
1111 {
1112 if (++retry > NSYS_MAXRETRY)
1113 NSYS_ERROR_TERMINATE("Too many I/O retries -- nsys_sendsip");
1114 continue;
1115 }
1116
1117 NSYS_ERROR_TERMINATE("Error writing Internet socket");
1118 }
1119 }
1120
1121
1122 /****************************************************************/
1123 /* sets a SIP address */
1124 /****************************************************************/
1125
nsys_netin_sipaddr(int fd,char * ip,unsigned short port)1126 int nsys_netin_sipaddr(int fd, char * ip, unsigned short port)
1127
1128 {
1129 struct sockaddr_in * addr;
1130
1131 if (fd == nsys_rtp_fd)
1132 {
1133 addr = &nsys_sip_rtp_addr;
1134 strcpy(nsys_sip_rtp_ip, ip);
1135 nsys_sip_rtp_inet_addr = inet_addr(ip);
1136 nsys_sip_rtp_port = port;
1137 nsys_sip_rtp_sin_port = htons(port);
1138 }
1139 else
1140 {
1141 addr = &nsys_sip_rtcp_addr;
1142 strcpy(nsys_sip_rtcp_ip, ip);
1143 nsys_sip_rtcp_inet_addr = inet_addr(ip);
1144 nsys_sip_rtcp_port = port;
1145 nsys_sip_rtcp_sin_port = htons(port);
1146 }
1147
1148 memset(&(addr->sin_zero), 0, 8);
1149 addr->sin_family = AF_INET;
1150 addr->sin_port = htons(port);
1151 if ((addr->sin_addr.s_addr = inet_addr(ip)) == -1)
1152 NSYS_ERROR_RETURN("Bad format for SIP address");
1153
1154 return NSYS_DONE;
1155 }
1156
1157 /****************************************************************/
1158 /* checks origin of incoming SIP */
1159 /****************************************************************/
1160
nsys_netin_siporigin(int fd,struct sockaddr_in * addr)1161 int nsys_netin_siporigin(int fd, struct sockaddr_in * addr)
1162
1163 {
1164 int ret = NSYS_ERROR;
1165
1166 if (fd == nsys_rtp_fd)
1167 {
1168 if ((addr->sin_addr.s_addr == nsys_sip_rtp_inet_addr) &&
1169 (addr->sin_port == nsys_sip_rtp_sin_port))
1170 ret = NSYS_DONE;
1171 }
1172 else
1173 {
1174 if ((addr->sin_addr.s_addr == nsys_sip_rtcp_inet_addr) &&
1175 (addr->sin_port == nsys_sip_rtcp_sin_port))
1176 return ret = NSYS_DONE;
1177 }
1178
1179 if (ret == NSYS_ERROR)
1180 {
1181 nsys_stderr_size +=
1182 fprintf(stderr, "Network advisory: SIP from unknown source %s:%hu"
1183 " rejected\n", inet_ntoa(addr->sin_addr),
1184 ntohs(addr->sin_port));
1185 fflush(stderr);
1186 }
1187
1188 return ret;
1189 }
1190
1191 /****************************************************************/
1192 /* makes an array of media payloads */
1193 /****************************************************************/
1194
nsys_netin_make_marray(struct nsys_payinfo ** marray,char * media)1195 int nsys_netin_make_marray(struct nsys_payinfo ** marray, char * media)
1196
1197 {
1198 int size, i, len;
1199 char * eptr, * cptr;
1200
1201 i = size = 0;
1202 len = strlen(media);
1203
1204 while (i < len)
1205 {
1206 while ((i < len) && (media[i] == ' '))
1207 i++;
1208 size += (i < len);
1209 while ((i < len) && (media[i] != ' '))
1210 i++;
1211 }
1212
1213 if (!size)
1214 return size;
1215
1216 *marray = calloc(size, sizeof(struct nsys_payinfo));
1217 cptr = media;
1218
1219 for (i = 0; i < size; i++)
1220 {
1221 (*marray)[i].pindex = i;
1222 (*marray)[i].ptype = (unsigned char)strtoul(cptr, &eptr, 10);
1223 cptr = eptr;
1224 }
1225
1226 return size;
1227
1228 }
1229
1230
1231 /****************************************************************/
1232 /* sets media payloads */
1233 /****************************************************************/
1234
nsys_netin_set_marray(char * line,struct nsys_payinfo marray[],int mlen)1235 int nsys_netin_set_marray(char * line, struct nsys_payinfo marray[], int mlen)
1236
1237 {
1238 unsigned short ptype; /* sscanf needs a short, not a char */
1239 char name[32];
1240 int srate;
1241 int i, num;
1242
1243 num = sscanf(line, "a=rtpmap:%hu %31[^/]/%i", &ptype, name, &srate);
1244
1245 if ((num != 2) && (num != 3))
1246 return 0;
1247
1248 i = 0;
1249 while (i < mlen)
1250 {
1251 if (marray[i].ptype == (unsigned char)ptype)
1252 break;
1253 i++;
1254 }
1255
1256 if (i == mlen)
1257 return 0;
1258
1259 strcpy(marray[i].name, name);
1260
1261 if (num == 3)
1262 marray[i].srate = srate;
1263 else
1264 marray[i].srate = -1;
1265
1266 return 1;
1267 }
1268
1269
1270 /****************************************************************/
1271 /* checks validity of payload ptype */
1272 /****************************************************************/
1273
nsys_netin_payvalid(struct nsys_payinfo marray[],int mlen,int fd)1274 int nsys_netin_payvalid(struct nsys_payinfo marray[], int mlen,
1275 int fd)
1276
1277
1278 {
1279 int i, j;
1280 char line[NSYS_UDPMAXSIZE+1];
1281
1282 for (i = 0; i < mlen; i++)
1283 for (j = 0; j < NSYS_RTP_PAYSIZE; j++)
1284 if (!strcasecmp(marray[i].name, nsys_payload_types[j].name))
1285 {
1286 if (nsys_msession || (marray[i].srate == -1) ||
1287 (marray[i].srate == nsys_payload_types[j].srate))
1288 return 1;
1289
1290 if (fd == nsys_rtp_fd)
1291 {
1292 nsys_warning(NSYS_WARN_STANDARD,
1293 "Rejecting an INVITE due to SAOL srate mismatch");
1294
1295 sprintf(line, "(local srate %iHz, remote srate %iHz)",
1296 nsys_payload_types[j].srate, marray[i].srate);
1297
1298 nsys_warning(NSYS_WARN_STANDARD, line);
1299 }
1300
1301 return 0;
1302 }
1303
1304 if (fd == nsys_rtp_fd)
1305 {
1306 nsys_warning(NSYS_WARN_STANDARD,
1307 "Rejecting an INVITE, no common RTP payloads");
1308 nsys_warning(NSYS_WARN_STANDARD,
1309 "(probably caused by local or remote out-of-date software)");
1310 nsys_warning(NSYS_WARN_STANDARD,
1311 "Download new version at:"
1312 " http://www.cs.berkeley.edu/~lazzaro/sa/index.html");
1313 }
1314 return 0;
1315 }
1316
1317 /****************************************************************/
1318 /* sets payload information in source */
1319 /****************************************************************/
1320
nsys_netin_payset(struct nsys_source * sptr,struct nsys_payinfo marray[],int mlen)1321 void nsys_netin_payset(struct nsys_source * sptr, struct nsys_payinfo marray[],
1322 int mlen)
1323
1324
1325 {
1326 int i, j;
1327
1328 for (i = 0; i < mlen; i++)
1329 for (j = 0; j < NSYS_RTP_PAYSIZE; j++)
1330 if (!strcasecmp(marray[i].name, nsys_payload_types[j].name))
1331 {
1332 sptr->ptype = marray[i].ptype;
1333 sptr->pindex = nsys_payload_types[j].pindex;
1334 if ((sptr->srate = marray[i].srate) < 0)
1335 sptr->srate = nsys_payload_types[j].srate;
1336 return;
1337 }
1338 }
1339
1340 /****************************************************************/
1341 /* checks for a SIP replay attack */
1342 /****************************************************************/
1343
nsys_netin_noreplay(char * ip,unsigned short port,unsigned long sdp_time)1344 int nsys_netin_noreplay(char * ip, unsigned short port, unsigned long sdp_time)
1345
1346 {
1347 struct nsys_source * sptr = nsys_srcroot;
1348 struct sockaddr_in ipaddr;
1349 int ret = 1;
1350
1351 if (sptr)
1352 {
1353 memset(&ipaddr, 0, sizeof(struct sockaddr_in));
1354 ipaddr.sin_port = htons(port);
1355 ipaddr.sin_family = AF_INET;
1356 ipaddr.sin_addr.s_addr = inet_addr(ip);
1357
1358 do {
1359 if ((!memcmp(&ipaddr, sptr->sdp_addr, sizeof(struct sockaddr_in))) &&
1360 (sptr->siptime > sdp_time))
1361 ret = 0;
1362 } while ((sptr = sptr->next) != nsys_srcroot);
1363 }
1364
1365 return ret;
1366 }
1367
1368 /* end Network library -- SIP functions */
1369
1370
1371