diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
commit | 55f4e4a5ec657a017e3bf75299ad71fd1c968dd3 (patch) | |
tree | 550ce922ea0e125ac6a9738210ce2939bf2fe901 /slirp/udp.c | |
parent | 413f05aaf54fa08c0ae7e997327a4f4a473c0a8d (diff) | |
download | external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.zip external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.tar.gz external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.tar.bz2 |
Initial Contribution
Diffstat (limited to 'slirp/udp.c')
-rw-r--r-- | slirp/udp.c | 204 |
1 files changed, 114 insertions, 90 deletions
diff --git a/slirp/udp.c b/slirp/udp.c index 0d70970..d96251d 100644 --- a/slirp/udp.c +++ b/slirp/udp.c @@ -37,8 +37,8 @@ /* * Changes and additions relating to SLiRP * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the + * + * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ @@ -66,26 +66,26 @@ udp_init() { udb.so_next = udb.so_prev = &udb; } -/* m->m_data points at ip packet header - * m->m_len length ip packet +/* m->m_data points at ip packet header + * m->m_len length ip packet * ip->ip_len length data (IPDU) */ void udp_input(m, iphlen) - register struct mbuf *m; + register MBuf m; int iphlen; { register struct ip *ip; register struct udphdr *uh; -/* struct mbuf *opts = 0;*/ +/* MBuf opts = 0;*/ int len; - struct ip save_ip; + struct ip save_ip; struct socket *so; - + DEBUG_CALL("udp_input"); DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("iphlen = %d", iphlen); - + udpstat.udps_ipackets++; /* @@ -95,14 +95,14 @@ udp_input(m, iphlen) * with options still present. */ if(iphlen > sizeof(struct ip)) { - ip_stripoptions(m, (struct mbuf *)0); + ip_stripoptions(m, (MBuf )0); iphlen = sizeof(struct ip); } /* * Get IP and UDP header together in first mbuf. */ - ip = mtod(m, struct ip *); + ip = MBUF_TO(m, struct ip *); uh = (struct udphdr *)((caddr_t)ip + iphlen); /* @@ -116,15 +116,15 @@ udp_input(m, iphlen) udpstat.udps_badlen++; goto bad; } - m_adj(m, len - ip->ip_len); + mbuf_trim(m, len - ip->ip_len); ip->ip_len = len; } - + /* * Save a copy of the IP header in case we want restore it * for sending an ICMP error message in response. */ - save_ip = *ip; + save_ip = *ip; save_ip.ip_len+= iphlen; /* tcp_input subtracts this */ /* @@ -136,8 +136,8 @@ udp_input(m, iphlen) ((struct ipovly *)ip)->ih_x1 = 0; ((struct ipovly *)ip)->ih_len = uh->uh_ulen; /* keep uh_sum for ICMP reply - * uh->uh_sum = cksum(m, len + sizeof (struct ip)); - * if (uh->uh_sum) { + * uh->uh_sum = cksum(m, len + sizeof (struct ip)); + * if (uh->uh_sum) { */ if(cksum(m, len + sizeof(struct ip))) { udpstat.udps_badsum++; @@ -168,7 +168,7 @@ udp_input(m, iphlen) if (so->so_lport != uh->uh_sport || so->so_laddr.s_addr != ip->ip_src.s_addr) { struct socket *tmp; - + for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) { if (tmp->so_lport == uh->uh_sport && tmp->so_laddr.s_addr == ip->ip_src.s_addr) { @@ -185,7 +185,7 @@ udp_input(m, iphlen) udp_last_so = so; } } - + if (so == NULL) { /* * If there's no socket for this packet, @@ -193,31 +193,32 @@ udp_input(m, iphlen) */ if ((so = socreate()) == NULL) goto bad; if(udp_attach(so) == -1) { - DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", + DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", errno,strerror(errno))); sofree(so); goto bad; } - + /* * Setup fields */ /* udp_last_so = so; */ so->so_laddr = ip->ip_src; so->so_lport = uh->uh_sport; - so->so_faddr = ip->ip_dst; /* XXX */ - so->so_fport = uh->uh_dport; /* XXX */ - + if ((so->so_iptos = udp_tos(so)) == 0) so->so_iptos = ip->ip_tos; - + /* * XXXXX Here, check if it's in udpexec_list, * and if it is, do the fork_exec() etc. */ } - iphlen += sizeof(struct udphdr); + so->so_faddr = ip->ip_dst; /* XXX */ + so->so_fport = uh->uh_dport; /* XXX */ + + iphlen += sizeof(struct udphdr); m->m_len -= iphlen; m->m_data += iphlen; @@ -232,10 +233,10 @@ udp_input(m, iphlen) m->m_data -= iphlen; *ip=save_ip; DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno))); - icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); + icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); } - m_free(so->so_m); /* used for ICMP if error on sorecvfrom */ + mbuf_free(so->so_m); /* used for ICMP if error on sorecvfrom */ /* restore the orig mbuf packet */ m->m_len += iphlen; @@ -245,12 +246,12 @@ udp_input(m, iphlen) return; bad: - m_freem(m); - /* if (opts) m_freem(opts); */ + mbuf_free(m); + /* if (opts) mbuf_free(opts); */ return; } -int udp_output2(struct socket *so, struct mbuf *m, +int udp_output2(struct socket *so, MBuf m, struct sockaddr_in *saddr, struct sockaddr_in *daddr, int iptos) { @@ -268,12 +269,12 @@ int udp_output2(struct socket *so, struct mbuf *m, */ m->m_data -= sizeof(struct udpiphdr); m->m_len += sizeof(struct udpiphdr); - + /* * Fill in mbuf with extended UDP header * and addresses and length put into network format. */ - ui = mtod(m, struct udpiphdr *); + ui = MBUF_TO(m, struct udpiphdr *); ui->ui_next = ui->ui_prev = 0; ui->ui_x1 = 0; ui->ui_pr = IPPROTO_UDP; @@ -297,15 +298,15 @@ int udp_output2(struct socket *so, struct mbuf *m, ((struct ip *)ui)->ip_ttl = ip_defttl; ((struct ip *)ui)->ip_tos = iptos; - + udpstat.udps_opackets++; - + error = ip_output(so, m); - + return (error); } -int udp_output(struct socket *so, struct mbuf *m, +int udp_output(struct socket *so, MBuf m, struct sockaddr_in *addr) { @@ -319,7 +320,7 @@ int udp_output(struct socket *so, struct mbuf *m, } daddr.sin_addr = so->so_laddr; daddr.sin_port = so->so_lport; - + return udp_output2(so, m, &saddr, &daddr, so->so_iptos); } @@ -328,7 +329,7 @@ udp_attach(so) struct socket *so; { struct sockaddr_in addr; - + if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) { /* * Here, we bind() the socket. Although not really needed @@ -361,7 +362,7 @@ udp_detach(so) struct socket *so; { closesocket(so->s); - /* if (so->so_m) m_free(so->so_m); done by sofree */ + /* if (so->so_m) mbuf_free(so->so_m); done by sofree */ sofree(so); } @@ -379,7 +380,7 @@ udp_tos(so) struct socket *so; { int i = 0; - + while(udptos[i].tos) { if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) || (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) { @@ -388,7 +389,7 @@ udp_tos(so) } i++; } - + return 0; } @@ -402,7 +403,7 @@ udp_tos(so) void udp_emu(so, m) struct socket *so; - struct mbuf *m; + MBuf m; { struct sockaddr_in addr; int addrlen = sizeof(addr); @@ -411,17 +412,17 @@ udp_emu(so, m) CTL_MSG *nmsg; char buff[sizeof(CTL_MSG)]; u_char type; - + struct talk_request { struct talk_request *next; struct socket *udp_so; struct socket *tcp_so; } *req; - - static struct talk_request *req_tbl = 0; - + + static struct talk_request *req_tbl = 0; + #endif - + struct cu_header { uint16_t d_family; // destination family uint16_t d_port; // destination port @@ -448,7 +449,7 @@ struct cu_header { */ if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) return; - + #define IS_OLD (so->so_emu == EMU_TALK) #define COPY_MSG(dest, src) { dest->type = src->type; \ @@ -465,24 +466,24 @@ struct cu_header { if (IS_OLD) { /* old talk */ - omsg = mtod(m, CTL_MSG_OLD*); + omsg = MBUF_TO(m, CTL_MSG_OLD*); nmsg = (CTL_MSG *) buff; type = omsg->type; OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port; OTOSIN(omsg, ctl_addr)->sin_addr = our_addr; strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD); - } else { /* new talk */ + } else { /* new talk */ omsg = (CTL_MSG_OLD *) buff; - nmsg = mtod(m, CTL_MSG *); + nmsg = MBUF_TO(m, CTL_MSG *); type = nmsg->type; OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port; OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr; strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD); } - - if (type == LOOK_UP) + + if (type == LOOK_UP) return; /* for LOOK_UP this is enough */ - + if (IS_OLD) { /* make a copy of the message */ COPY_MSG(nmsg, omsg); nmsg->vers = 1; @@ -501,75 +502,75 @@ struct cu_header { * ports, 517 and 518. This is why we have two copies * of the message, one in old talk and one in new talk * format. - */ + */ if (type == ANNOUNCE) { int s; u_short temp_port; - + for(req = req_tbl; req; req = req->next) if (so == req->udp_so) break; /* found it */ - + if (!req) { /* no entry for so, create new */ req = (struct talk_request *) malloc(sizeof(struct talk_request)); req->udp_so = so; - req->tcp_so = solisten(0, - OTOSIN(omsg, addr)->sin_addr.s_addr, + req->tcp_so = solisten(0, + OTOSIN(omsg, addr)->sin_addr.s_addr, OTOSIN(omsg, addr)->sin_port, SS_FACCEPTONCE); req->next = req_tbl; req_tbl = req; - } - + } + /* replace port number in addr field */ addrlen = sizeof(addr); - getsockname(req->tcp_so->s, + getsockname(req->tcp_so->s, (struct sockaddr *) &addr, - &addrlen); + &addrlen); OTOSIN(omsg, addr)->sin_port = addr.sin_port; OTOSIN(omsg, addr)->sin_addr = our_addr; OTOSIN(nmsg, addr)->sin_port = addr.sin_port; - OTOSIN(nmsg, addr)->sin_addr = our_addr; - + OTOSIN(nmsg, addr)->sin_addr = our_addr; + /* send LEAVE_INVITEs */ temp_port = OTOSIN(omsg, ctl_addr)->sin_port; OTOSIN(omsg, ctl_addr)->sin_port = 0; OTOSIN(nmsg, ctl_addr)->sin_port = 0; - omsg->type = nmsg->type = LEAVE_INVITE; - + omsg->type = nmsg->type = LEAVE_INVITE; + s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); addr.sin_addr = our_addr; addr.sin_family = AF_INET; addr.sin_port = htons(517); - sendto(s, (char *)omsg, sizeof(*omsg), 0, + sendto(s, (char *)omsg, sizeof(*omsg), 0, (struct sockaddr *)&addr, sizeof(addr)); addr.sin_port = htons(518); sendto(s, (char *)nmsg, sizeof(*nmsg), 0, (struct sockaddr *) &addr, sizeof(addr)); closesocket(s) ; - omsg->type = nmsg->type = ANNOUNCE; + omsg->type = nmsg->type = ANNOUNCE; OTOSIN(omsg, ctl_addr)->sin_port = temp_port; OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; } - - /* + + /* * If it is a DELETE message, we send a copy to the * local daemons. Then we delete the entry corresponding * to our socket from the request table. */ - + if (type == DELETE) { struct talk_request *temp_req, *req_next; int s; u_short temp_port; - + temp_port = OTOSIN(omsg, ctl_addr)->sin_port; OTOSIN(omsg, ctl_addr)->sin_port = 0; OTOSIN(nmsg, ctl_addr)->sin_port = 0; - + s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); addr.sin_addr = our_addr; addr.sin_family = AF_INET; @@ -580,7 +581,7 @@ struct cu_header { sendto(s, (char *)nmsg, sizeof(*nmsg), 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(s); - + OTOSIN(omsg, ctl_addr)->sin_port = temp_port; OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; @@ -603,26 +604,26 @@ struct cu_header { } } } - - return; + + return; #endif - + case EMU_CUSEEME: - + /* * Cu-SeeMe emulation. * Hopefully the packet is more that 16 bytes long. We don't * do any other tests, just replace the address and port * fields. - */ + */ if (m->m_len >= sizeof (*cu_head)) { if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) return; - cu_head = mtod(m, struct cu_header *); + cu_head = MBUF_TO(m, struct cu_header *); cu_head->s_port = addr.sin_port; cu_head->so_addr = our_addr.s_addr; } - + return; } } @@ -636,14 +637,15 @@ udp_listen(port, laddr, lport, flags) { struct sockaddr_in addr; struct socket *so; - int addrlen = sizeof(struct sockaddr_in), opt = 1; - + int addrlen = sizeof(struct sockaddr_in); + if ((so = socreate()) == NULL) { free(so); return NULL; } so->s = socket(AF_INET,SOCK_DGRAM,0); so->so_expire = curtime + SO_EXPIRE; + so->so_hport = port; insque(so,&udb); addr.sin_family = AF_INET; @@ -654,22 +656,44 @@ udp_listen(port, laddr, lport, flags) udp_detach(so); return NULL; } - setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); -/* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */ - + socket_set_xreuseaddr(so->s); + getsockname(so->s,(struct sockaddr *)&addr,&addrlen); so->so_fport = addr.sin_port; if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) so->so_faddr = alias_addr; else so->so_faddr = addr.sin_addr; - + so->so_lport = lport; so->so_laddr.s_addr = laddr; if (flags != SS_FACCEPTONCE) so->so_expire = 0; - + so->so_state = SS_ISFCONNECTED; - + return so; } + +int udp_unlisten (u_int port) +{ + struct socket *so; + + for (so = udb.so_next; so != &udb; so = so->so_next) { + if (so->so_hport == htons(port)) { + break; + } + } + + if (so == &udb) + return -1; + + sofcantrcvmore( so ); + sofcantsendmore( so ); + close( so->s ); + so->s = -1; + sofree( so ); + return 0; +} + + |