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