Revision 5fafdf24 slirp/udp.c
b/slirp/udp.c | ||
---|---|---|
37 | 37 |
/* |
38 | 38 |
* Changes and additions relating to SLiRP |
39 | 39 |
* Copyright (c) 1995 Danny Gasparovski. |
40 |
*
|
|
41 |
* Please read the file COPYRIGHT for the
|
|
40 |
* |
|
41 |
* Please read the file COPYRIGHT for the |
|
42 | 42 |
* terms and conditions of the copyright. |
43 | 43 |
*/ |
44 | 44 |
|
... | ... | |
66 | 66 |
{ |
67 | 67 |
udb.so_next = udb.so_prev = &udb; |
68 | 68 |
} |
69 |
/* m->m_data points at ip packet header
|
|
70 |
* m->m_len length ip packet
|
|
69 |
/* m->m_data points at ip packet header |
|
70 |
* m->m_len length ip packet |
|
71 | 71 |
* ip->ip_len length data (IPDU) |
72 | 72 |
*/ |
73 | 73 |
void |
... | ... | |
79 | 79 |
register struct udphdr *uh; |
80 | 80 |
/* struct mbuf *opts = 0;*/ |
81 | 81 |
int len; |
82 |
struct ip save_ip;
|
|
82 |
struct ip save_ip; |
|
83 | 83 |
struct socket *so; |
84 |
|
|
84 |
|
|
85 | 85 |
DEBUG_CALL("udp_input"); |
86 | 86 |
DEBUG_ARG("m = %lx", (long)m); |
87 | 87 |
DEBUG_ARG("iphlen = %d", iphlen); |
88 |
|
|
88 |
|
|
89 | 89 |
udpstat.udps_ipackets++; |
90 | 90 |
|
91 | 91 |
/* |
... | ... | |
119 | 119 |
m_adj(m, len - ip->ip_len); |
120 | 120 |
ip->ip_len = len; |
121 | 121 |
} |
122 |
|
|
122 |
|
|
123 | 123 |
/* |
124 | 124 |
* Save a copy of the IP header in case we want restore it |
125 | 125 |
* for sending an ICMP error message in response. |
126 | 126 |
*/ |
127 |
save_ip = *ip;
|
|
127 |
save_ip = *ip; |
|
128 | 128 |
save_ip.ip_len+= iphlen; /* tcp_input subtracts this */ |
129 | 129 |
|
130 | 130 |
/* |
... | ... | |
136 | 136 |
((struct ipovly *)ip)->ih_x1 = 0; |
137 | 137 |
((struct ipovly *)ip)->ih_len = uh->uh_ulen; |
138 | 138 |
/* keep uh_sum for ICMP reply |
139 |
* uh->uh_sum = cksum(m, len + sizeof (struct ip));
|
|
140 |
* if (uh->uh_sum) {
|
|
139 |
* uh->uh_sum = cksum(m, len + sizeof (struct ip)); |
|
140 |
* if (uh->uh_sum) { |
|
141 | 141 |
*/ |
142 | 142 |
if(cksum(m, len + sizeof(struct ip))) { |
143 | 143 |
udpstat.udps_badsum++; |
... | ... | |
168 | 168 |
if (so->so_lport != uh->uh_sport || |
169 | 169 |
so->so_laddr.s_addr != ip->ip_src.s_addr) { |
170 | 170 |
struct socket *tmp; |
171 |
|
|
171 |
|
|
172 | 172 |
for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) { |
173 | 173 |
if (tmp->so_lport == uh->uh_sport && |
174 | 174 |
tmp->so_laddr.s_addr == ip->ip_src.s_addr) { |
... | ... | |
185 | 185 |
udp_last_so = so; |
186 | 186 |
} |
187 | 187 |
} |
188 |
|
|
188 |
|
|
189 | 189 |
if (so == NULL) { |
190 | 190 |
/* |
191 | 191 |
* If there's no socket for this packet, |
... | ... | |
193 | 193 |
*/ |
194 | 194 |
if ((so = socreate()) == NULL) goto bad; |
195 | 195 |
if(udp_attach(so) == -1) { |
196 |
DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
|
|
196 |
DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", |
|
197 | 197 |
errno,strerror(errno))); |
198 | 198 |
sofree(so); |
199 | 199 |
goto bad; |
200 | 200 |
} |
201 |
|
|
201 |
|
|
202 | 202 |
/* |
203 | 203 |
* Setup fields |
204 | 204 |
*/ |
205 | 205 |
/* udp_last_so = so; */ |
206 | 206 |
so->so_laddr = ip->ip_src; |
207 | 207 |
so->so_lport = uh->uh_sport; |
208 |
|
|
208 |
|
|
209 | 209 |
if ((so->so_iptos = udp_tos(so)) == 0) |
210 | 210 |
so->so_iptos = ip->ip_tos; |
211 |
|
|
211 |
|
|
212 | 212 |
/* |
213 | 213 |
* XXXXX Here, check if it's in udpexec_list, |
214 | 214 |
* and if it is, do the fork_exec() etc. |
... | ... | |
233 | 233 |
m->m_data -= iphlen; |
234 | 234 |
*ip=save_ip; |
235 | 235 |
DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno))); |
236 |
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
|
|
236 |
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); |
|
237 | 237 |
} |
238 | 238 |
|
239 | 239 |
m_free(so->so_m); /* used for ICMP if error on sorecvfrom */ |
... | ... | |
251 | 251 |
return; |
252 | 252 |
} |
253 | 253 |
|
254 |
int udp_output2(struct socket *so, struct mbuf *m,
|
|
254 |
int udp_output2(struct socket *so, struct mbuf *m, |
|
255 | 255 |
struct sockaddr_in *saddr, struct sockaddr_in *daddr, |
256 | 256 |
int iptos) |
257 | 257 |
{ |
... | ... | |
269 | 269 |
*/ |
270 | 270 |
m->m_data -= sizeof(struct udpiphdr); |
271 | 271 |
m->m_len += sizeof(struct udpiphdr); |
272 |
|
|
272 |
|
|
273 | 273 |
/* |
274 | 274 |
* Fill in mbuf with extended UDP header |
275 | 275 |
* and addresses and length put into network format. |
... | ... | |
298 | 298 |
|
299 | 299 |
((struct ip *)ui)->ip_ttl = ip_defttl; |
300 | 300 |
((struct ip *)ui)->ip_tos = iptos; |
301 |
|
|
301 |
|
|
302 | 302 |
udpstat.udps_opackets++; |
303 |
|
|
303 |
|
|
304 | 304 |
error = ip_output(so, m); |
305 |
|
|
305 |
|
|
306 | 306 |
return (error); |
307 | 307 |
} |
308 | 308 |
|
309 |
int udp_output(struct socket *so, struct mbuf *m,
|
|
309 |
int udp_output(struct socket *so, struct mbuf *m, |
|
310 | 310 |
struct sockaddr_in *addr) |
311 | 311 |
|
312 | 312 |
{ |
... | ... | |
320 | 320 |
} |
321 | 321 |
daddr.sin_addr = so->so_laddr; |
322 | 322 |
daddr.sin_port = so->so_lport; |
323 |
|
|
323 |
|
|
324 | 324 |
return udp_output2(so, m, &saddr, &daddr, so->so_iptos); |
325 | 325 |
} |
326 | 326 |
|
... | ... | |
329 | 329 |
struct socket *so; |
330 | 330 |
{ |
331 | 331 |
struct sockaddr_in addr; |
332 |
|
|
332 |
|
|
333 | 333 |
if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) { |
334 | 334 |
/* |
335 | 335 |
* Here, we bind() the socket. Although not really needed |
... | ... | |
380 | 380 |
struct socket *so; |
381 | 381 |
{ |
382 | 382 |
int i = 0; |
383 |
|
|
383 |
|
|
384 | 384 |
while(udptos[i].tos) { |
385 | 385 |
if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) || |
386 | 386 |
(udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) { |
... | ... | |
389 | 389 |
} |
390 | 390 |
i++; |
391 | 391 |
} |
392 |
|
|
392 |
|
|
393 | 393 |
return 0; |
394 | 394 |
} |
395 | 395 |
|
... | ... | |
412 | 412 |
CTL_MSG *nmsg; |
413 | 413 |
char buff[sizeof(CTL_MSG)]; |
414 | 414 |
u_char type; |
415 |
|
|
415 |
|
|
416 | 416 |
struct talk_request { |
417 | 417 |
struct talk_request *next; |
418 | 418 |
struct socket *udp_so; |
419 | 419 |
struct socket *tcp_so; |
420 | 420 |
} *req; |
421 |
|
|
422 |
static struct talk_request *req_tbl = 0;
|
|
423 |
|
|
421 |
|
|
422 |
static struct talk_request *req_tbl = 0; |
|
423 |
|
|
424 | 424 |
#endif |
425 |
|
|
425 |
|
|
426 | 426 |
struct cu_header { |
427 | 427 |
uint16_t d_family; // destination family |
428 | 428 |
uint16_t d_port; // destination port |
... | ... | |
449 | 449 |
*/ |
450 | 450 |
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) |
451 | 451 |
return; |
452 |
|
|
452 |
|
|
453 | 453 |
#define IS_OLD (so->so_emu == EMU_TALK) |
454 | 454 |
|
455 | 455 |
#define COPY_MSG(dest, src) { dest->type = src->type; \ |
... | ... | |
472 | 472 |
OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port; |
473 | 473 |
OTOSIN(omsg, ctl_addr)->sin_addr = our_addr; |
474 | 474 |
strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD); |
475 |
} else { /* new talk */
|
|
475 |
} else { /* new talk */ |
|
476 | 476 |
omsg = (CTL_MSG_OLD *) buff; |
477 | 477 |
nmsg = mtod(m, CTL_MSG *); |
478 | 478 |
type = nmsg->type; |
... | ... | |
480 | 480 |
OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr; |
481 | 481 |
strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD); |
482 | 482 |
} |
483 |
|
|
484 |
if (type == LOOK_UP)
|
|
483 |
|
|
484 |
if (type == LOOK_UP) |
|
485 | 485 |
return; /* for LOOK_UP this is enough */ |
486 |
|
|
486 |
|
|
487 | 487 |
if (IS_OLD) { /* make a copy of the message */ |
488 | 488 |
COPY_MSG(nmsg, omsg); |
489 | 489 |
nmsg->vers = 1; |
... | ... | |
502 | 502 |
* ports, 517 and 518. This is why we have two copies |
503 | 503 |
* of the message, one in old talk and one in new talk |
504 | 504 |
* format. |
505 |
*/
|
|
505 |
*/ |
|
506 | 506 |
|
507 | 507 |
if (type == ANNOUNCE) { |
508 | 508 |
int s; |
509 | 509 |
u_short temp_port; |
510 |
|
|
510 |
|
|
511 | 511 |
for(req = req_tbl; req; req = req->next) |
512 | 512 |
if (so == req->udp_so) |
513 | 513 |
break; /* found it */ |
514 |
|
|
514 |
|
|
515 | 515 |
if (!req) { /* no entry for so, create new */ |
516 | 516 |
req = (struct talk_request *) |
517 | 517 |
malloc(sizeof(struct talk_request)); |
518 | 518 |
req->udp_so = so; |
519 |
req->tcp_so = solisten(0,
|
|
520 |
OTOSIN(omsg, addr)->sin_addr.s_addr,
|
|
519 |
req->tcp_so = solisten(0, |
|
520 |
OTOSIN(omsg, addr)->sin_addr.s_addr, |
|
521 | 521 |
OTOSIN(omsg, addr)->sin_port, |
522 | 522 |
SS_FACCEPTONCE); |
523 | 523 |
req->next = req_tbl; |
524 | 524 |
req_tbl = req; |
525 |
}
|
|
526 |
|
|
525 |
} |
|
526 |
|
|
527 | 527 |
/* replace port number in addr field */ |
528 | 528 |
addrlen = sizeof(addr); |
529 |
getsockname(req->tcp_so->s,
|
|
529 |
getsockname(req->tcp_so->s, |
|
530 | 530 |
(struct sockaddr *) &addr, |
531 |
&addrlen);
|
|
531 |
&addrlen); |
|
532 | 532 |
OTOSIN(omsg, addr)->sin_port = addr.sin_port; |
533 | 533 |
OTOSIN(omsg, addr)->sin_addr = our_addr; |
534 | 534 |
OTOSIN(nmsg, addr)->sin_port = addr.sin_port; |
535 |
OTOSIN(nmsg, addr)->sin_addr = our_addr;
|
|
536 |
|
|
535 |
OTOSIN(nmsg, addr)->sin_addr = our_addr; |
|
536 |
|
|
537 | 537 |
/* send LEAVE_INVITEs */ |
538 | 538 |
temp_port = OTOSIN(omsg, ctl_addr)->sin_port; |
539 | 539 |
OTOSIN(omsg, ctl_addr)->sin_port = 0; |
540 | 540 |
OTOSIN(nmsg, ctl_addr)->sin_port = 0; |
541 |
omsg->type = nmsg->type = LEAVE_INVITE;
|
|
542 |
|
|
541 |
omsg->type = nmsg->type = LEAVE_INVITE; |
|
542 |
|
|
543 | 543 |
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); |
544 | 544 |
addr.sin_addr = our_addr; |
545 | 545 |
addr.sin_family = AF_INET; |
546 | 546 |
addr.sin_port = htons(517); |
547 |
sendto(s, (char *)omsg, sizeof(*omsg), 0,
|
|
547 |
sendto(s, (char *)omsg, sizeof(*omsg), 0, |
|
548 | 548 |
(struct sockaddr *)&addr, sizeof(addr)); |
549 | 549 |
addr.sin_port = htons(518); |
550 | 550 |
sendto(s, (char *)nmsg, sizeof(*nmsg), 0, |
551 | 551 |
(struct sockaddr *) &addr, sizeof(addr)); |
552 | 552 |
closesocket(s) ; |
553 | 553 |
|
554 |
omsg->type = nmsg->type = ANNOUNCE;
|
|
554 |
omsg->type = nmsg->type = ANNOUNCE; |
|
555 | 555 |
OTOSIN(omsg, ctl_addr)->sin_port = temp_port; |
556 | 556 |
OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; |
557 | 557 |
} |
558 |
|
|
559 |
/*
|
|
558 |
|
|
559 |
/* |
|
560 | 560 |
* If it is a DELETE message, we send a copy to the |
561 | 561 |
* local daemons. Then we delete the entry corresponding |
562 | 562 |
* to our socket from the request table. |
563 | 563 |
*/ |
564 |
|
|
564 |
|
|
565 | 565 |
if (type == DELETE) { |
566 | 566 |
struct talk_request *temp_req, *req_next; |
567 | 567 |
int s; |
568 | 568 |
u_short temp_port; |
569 |
|
|
569 |
|
|
570 | 570 |
temp_port = OTOSIN(omsg, ctl_addr)->sin_port; |
571 | 571 |
OTOSIN(omsg, ctl_addr)->sin_port = 0; |
572 | 572 |
OTOSIN(nmsg, ctl_addr)->sin_port = 0; |
573 |
|
|
573 |
|
|
574 | 574 |
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); |
575 | 575 |
addr.sin_addr = our_addr; |
576 | 576 |
addr.sin_family = AF_INET; |
... | ... | |
581 | 581 |
sendto(s, (char *)nmsg, sizeof(*nmsg), 0, |
582 | 582 |
(struct sockaddr *)&addr, sizeof(addr)); |
583 | 583 |
closesocket(s); |
584 |
|
|
584 |
|
|
585 | 585 |
OTOSIN(omsg, ctl_addr)->sin_port = temp_port; |
586 | 586 |
OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; |
587 | 587 |
|
... | ... | |
604 | 604 |
} |
605 | 605 |
} |
606 | 606 |
} |
607 |
|
|
608 |
return;
|
|
607 |
|
|
608 |
return; |
|
609 | 609 |
#endif |
610 |
|
|
611 |
case EMU_CUSEEME: |
|
612 | 610 |
|
611 |
case EMU_CUSEEME: |
|
612 |
|
|
613 | 613 |
/* |
614 | 614 |
* Cu-SeeMe emulation. |
615 | 615 |
* Hopefully the packet is more that 16 bytes long. We don't |
616 | 616 |
* do any other tests, just replace the address and port |
617 | 617 |
* fields. |
618 |
*/
|
|
618 |
*/ |
|
619 | 619 |
if (m->m_len >= sizeof (*cu_head)) { |
620 | 620 |
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) |
621 | 621 |
return; |
... | ... | |
623 | 623 |
cu_head->s_port = addr.sin_port; |
624 | 624 |
cu_head->so_addr = our_addr.s_addr; |
625 | 625 |
} |
626 |
|
|
626 |
|
|
627 | 627 |
return; |
628 | 628 |
} |
629 | 629 |
} |
... | ... | |
638 | 638 |
struct sockaddr_in addr; |
639 | 639 |
struct socket *so; |
640 | 640 |
int addrlen = sizeof(struct sockaddr_in), opt = 1; |
641 |
|
|
641 |
|
|
642 | 642 |
if ((so = socreate()) == NULL) { |
643 | 643 |
free(so); |
644 | 644 |
return NULL; |
... | ... | |
657 | 657 |
} |
658 | 658 |
setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); |
659 | 659 |
/* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */ |
660 |
|
|
660 |
|
|
661 | 661 |
getsockname(so->s,(struct sockaddr *)&addr,&addrlen); |
662 | 662 |
so->so_fport = addr.sin_port; |
663 | 663 |
if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) |
664 | 664 |
so->so_faddr = alias_addr; |
665 | 665 |
else |
666 | 666 |
so->so_faddr = addr.sin_addr; |
667 |
|
|
667 |
|
|
668 | 668 |
so->so_lport = lport; |
669 | 669 |
so->so_laddr.s_addr = laddr; |
670 | 670 |
if (flags != SS_FACCEPTONCE) |
671 | 671 |
so->so_expire = 0; |
672 |
|
|
672 |
|
|
673 | 673 |
so->so_state = SS_ISFCONNECTED; |
674 |
|
|
674 |
|
|
675 | 675 |
return so; |
676 | 676 |
} |
Also available in: Unified diff