|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1988, 1990, 1993
3: * The Regents of the University of California. All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
1.1.1.6 root 13: * 3. Neither the name of the University nor the names of its contributors
1.1 root 14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: *
29: * @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94
30: * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp
31: */
32:
33: /*
34: * Changes and additions relating to SLiRP
35: * Copyright (c) 1995 Danny Gasparovski.
1.1.1.5 root 36: *
37: * Please read the file COPYRIGHT for the
1.1 root 38: * terms and conditions of the copyright.
39: */
40:
41: #include <slirp.h>
42: #include "ip_icmp.h"
43:
1.1.1.9 root 44: static uint8_t udp_tos(struct socket *so);
1.1.1.5 root 45:
1.1 root 46: void
1.1.1.7 root 47: udp_init(Slirp *slirp)
1.1 root 48: {
1.1.1.7 root 49: slirp->udb.so_next = slirp->udb.so_prev = &slirp->udb;
50: slirp->udp_last_so = &slirp->udb;
1.1 root 51: }
1.1.1.5 root 52: /* m->m_data points at ip packet header
53: * m->m_len length ip packet
1.1 root 54: * ip->ip_len length data (IPDU)
55: */
56: void
1.1.1.7 root 57: udp_input(register struct mbuf *m, int iphlen)
1.1 root 58: {
1.1.1.7 root 59: Slirp *slirp = m->slirp;
1.1 root 60: register struct ip *ip;
61: register struct udphdr *uh;
62: int len;
1.1.1.5 root 63: struct ip save_ip;
1.1 root 64: struct socket *so;
1.1.1.5 root 65:
1.1 root 66: DEBUG_CALL("udp_input");
67: DEBUG_ARG("m = %lx", (long)m);
68: DEBUG_ARG("iphlen = %d", iphlen);
1.1.1.5 root 69:
1.1 root 70: /*
71: * Strip IP options, if any; should skip this,
72: * make available to user, and use on returned packets,
73: * but we don't yet have a way to check the checksum
74: * with options still present.
75: */
76: if(iphlen > sizeof(struct ip)) {
77: ip_stripoptions(m, (struct mbuf *)0);
78: iphlen = sizeof(struct ip);
79: }
80:
81: /*
82: * Get IP and UDP header together in first mbuf.
83: */
84: ip = mtod(m, struct ip *);
85: uh = (struct udphdr *)((caddr_t)ip + iphlen);
86:
87: /*
88: * Make mbuf data length reflect UDP length.
89: * If not enough data to reflect UDP length, drop.
90: */
1.1.1.9 root 91: len = ntohs((uint16_t)uh->uh_ulen);
1.1 root 92:
93: if (ip->ip_len != len) {
94: if (len > ip->ip_len) {
95: goto bad;
96: }
97: m_adj(m, len - ip->ip_len);
98: ip->ip_len = len;
99: }
1.1.1.5 root 100:
1.1 root 101: /*
102: * Save a copy of the IP header in case we want restore it
103: * for sending an ICMP error message in response.
104: */
1.1.1.5 root 105: save_ip = *ip;
1.1 root 106: save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
107:
108: /*
109: * Checksum extended UDP header and data.
110: */
1.1.1.7 root 111: if (uh->uh_sum) {
1.1.1.6 root 112: memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr));
1.1 root 113: ((struct ipovly *)ip)->ih_x1 = 0;
114: ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
115: if(cksum(m, len + sizeof(struct ip))) {
116: goto bad;
117: }
118: }
119:
120: /*
121: * handle DHCP/BOOTP
122: */
1.1.1.10! root 123: if (ntohs(uh->uh_dport) == BOOTP_SERVER &&
! 124: (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr ||
! 125: ip->ip_dst.s_addr == 0xffffffff)) {
! 126: bootp_input(m);
! 127: goto bad;
! 128: }
1.1.1.6 root 129:
1.1 root 130: /*
131: * handle TFTP
132: */
1.1.1.10! root 133: if (ntohs(uh->uh_dport) == TFTP_SERVER &&
! 134: ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {
1.1 root 135: tftp_input(m);
136: goto bad;
137: }
138:
1.1.1.10! root 139: if (slirp->restricted) {
! 140: goto bad;
! 141: }
! 142:
1.1 root 143: /*
144: * Locate pcb for datagram.
145: */
1.1.1.7 root 146: so = slirp->udp_last_so;
1.1 root 147: if (so->so_lport != uh->uh_sport ||
148: so->so_laddr.s_addr != ip->ip_src.s_addr) {
149: struct socket *tmp;
1.1.1.5 root 150:
1.1.1.7 root 151: for (tmp = slirp->udb.so_next; tmp != &slirp->udb;
152: tmp = tmp->so_next) {
1.1 root 153: if (tmp->so_lport == uh->uh_sport &&
154: tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
155: so = tmp;
156: break;
157: }
158: }
1.1.1.7 root 159: if (tmp == &slirp->udb) {
1.1 root 160: so = NULL;
161: } else {
1.1.1.7 root 162: slirp->udp_last_so = so;
1.1 root 163: }
164: }
1.1.1.5 root 165:
1.1 root 166: if (so == NULL) {
167: /*
168: * If there's no socket for this packet,
169: * create one
170: */
1.1.1.7 root 171: so = socreate(slirp);
172: if (!so) {
173: goto bad;
174: }
1.1 root 175: if(udp_attach(so) == -1) {
1.1.1.5 root 176: DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
1.1 root 177: errno,strerror(errno)));
178: sofree(so);
179: goto bad;
180: }
1.1.1.5 root 181:
1.1 root 182: /*
183: * Setup fields
184: */
185: so->so_laddr = ip->ip_src;
186: so->so_lport = uh->uh_sport;
1.1.1.5 root 187:
1.1 root 188: if ((so->so_iptos = udp_tos(so)) == 0)
189: so->so_iptos = ip->ip_tos;
1.1.1.5 root 190:
1.1 root 191: /*
192: * XXXXX Here, check if it's in udpexec_list,
193: * and if it is, do the fork_exec() etc.
194: */
195: }
196:
1.1.1.4 root 197: so->so_faddr = ip->ip_dst; /* XXX */
198: so->so_fport = uh->uh_dport; /* XXX */
199:
1.1 root 200: iphlen += sizeof(struct udphdr);
201: m->m_len -= iphlen;
202: m->m_data += iphlen;
203:
204: /*
205: * Now we sendto() the packet.
206: */
207: if(sosendto(so,m) == -1) {
208: m->m_len += iphlen;
209: m->m_data -= iphlen;
210: *ip=save_ip;
211: DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
1.1.1.5 root 212: icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
1.1 root 213: }
214:
215: m_free(so->so_m); /* used for ICMP if error on sorecvfrom */
216:
217: /* restore the orig mbuf packet */
218: m->m_len += iphlen;
219: m->m_data -= iphlen;
220: *ip=save_ip;
221: so->so_m=m; /* ICMP backup */
222:
223: return;
224: bad:
1.1.1.10! root 225: m_free(m);
1.1 root 226: return;
227: }
228:
1.1.1.5 root 229: int udp_output2(struct socket *so, struct mbuf *m,
1.1 root 230: struct sockaddr_in *saddr, struct sockaddr_in *daddr,
231: int iptos)
232: {
233: register struct udpiphdr *ui;
234: int error = 0;
235:
236: DEBUG_CALL("udp_output");
237: DEBUG_ARG("so = %lx", (long)so);
238: DEBUG_ARG("m = %lx", (long)m);
239: DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr);
240: DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr);
241:
242: /*
243: * Adjust for header
244: */
245: m->m_data -= sizeof(struct udpiphdr);
246: m->m_len += sizeof(struct udpiphdr);
1.1.1.5 root 247:
1.1 root 248: /*
249: * Fill in mbuf with extended UDP header
250: * and addresses and length put into network format.
251: */
252: ui = mtod(m, struct udpiphdr *);
1.1.1.6 root 253: memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
1.1 root 254: ui->ui_x1 = 0;
255: ui->ui_pr = IPPROTO_UDP;
1.1.1.7 root 256: ui->ui_len = htons(m->m_len - sizeof(struct ip));
1.1 root 257: /* XXXXX Check for from-one-location sockets, or from-any-location sockets */
258: ui->ui_src = saddr->sin_addr;
259: ui->ui_dst = daddr->sin_addr;
260: ui->ui_sport = saddr->sin_port;
261: ui->ui_dport = daddr->sin_port;
262: ui->ui_ulen = ui->ui_len;
263:
264: /*
265: * Stuff checksum and output datagram.
266: */
267: ui->ui_sum = 0;
1.1.1.7 root 268: if ((ui->ui_sum = cksum(m, m->m_len)) == 0)
1.1 root 269: ui->ui_sum = 0xffff;
270: ((struct ip *)ui)->ip_len = m->m_len;
271:
1.1.1.5 root 272: ((struct ip *)ui)->ip_ttl = IPDEFTTL;
1.1 root 273: ((struct ip *)ui)->ip_tos = iptos;
1.1.1.5 root 274:
1.1 root 275: error = ip_output(so, m);
1.1.1.5 root 276:
1.1 root 277: return (error);
278: }
279:
1.1.1.5 root 280: int udp_output(struct socket *so, struct mbuf *m,
1.1 root 281: struct sockaddr_in *addr)
282:
283: {
1.1.1.7 root 284: Slirp *slirp = so->slirp;
1.1 root 285: struct sockaddr_in saddr, daddr;
286:
287: saddr = *addr;
1.1.1.7 root 288: if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
289: slirp->vnetwork_addr.s_addr) {
290: uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr;
291:
292: if ((so->so_faddr.s_addr & inv_mask) == inv_mask) {
293: saddr.sin_addr = slirp->vhost_addr;
294: } else if (addr->sin_addr.s_addr == loopback_addr.s_addr ||
295: so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
296: saddr.sin_addr = so->so_faddr;
297: }
1.1.1.3 root 298: }
1.1 root 299: daddr.sin_addr = so->so_laddr;
300: daddr.sin_port = so->so_lport;
1.1.1.5 root 301:
1.1 root 302: return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
303: }
304:
305: int
1.1.1.7 root 306: udp_attach(struct socket *so)
1.1 root 307: {
1.1.1.8 root 308: if((so->s = qemu_socket(AF_INET,SOCK_DGRAM,0)) != -1) {
309: so->so_expire = curtime + SO_EXPIRE;
310: insque(so, &so->slirp->udb);
1.1 root 311: }
312: return(so->s);
313: }
314:
315: void
1.1.1.7 root 316: udp_detach(struct socket *so)
1.1 root 317: {
318: closesocket(so->s);
319: sofree(so);
320: }
321:
1.1.1.5 root 322: static const struct tos_t udptos[] = {
1.1 root 323: {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */
324: {0, 0, 0, 0}
325: };
326:
1.1.1.9 root 327: static uint8_t
1.1.1.5 root 328: udp_tos(struct socket *so)
1.1 root 329: {
330: int i = 0;
1.1.1.5 root 331:
1.1 root 332: while(udptos[i].tos) {
333: if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
334: (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
335: so->so_emu = udptos[i].emu;
336: return udptos[i].tos;
337: }
338: i++;
339: }
1.1.1.5 root 340:
1.1 root 341: return 0;
342: }
343:
344: struct socket *
1.1.1.9 root 345: udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
1.1.1.7 root 346: u_int lport, int flags)
1.1 root 347: {
348: struct sockaddr_in addr;
349: struct socket *so;
1.1.1.6 root 350: socklen_t addrlen = sizeof(struct sockaddr_in), opt = 1;
1.1.1.5 root 351:
1.1.1.7 root 352: so = socreate(slirp);
353: if (!so) {
354: return NULL;
1.1 root 355: }
1.1.1.8 root 356: so->s = qemu_socket(AF_INET,SOCK_DGRAM,0);
1.1 root 357: so->so_expire = curtime + SO_EXPIRE;
1.1.1.7 root 358: insque(so, &slirp->udb);
1.1 root 359:
360: addr.sin_family = AF_INET;
1.1.1.7 root 361: addr.sin_addr.s_addr = haddr;
362: addr.sin_port = hport;
1.1 root 363:
364: if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
365: udp_detach(so);
366: return NULL;
367: }
368: setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
1.1.1.5 root 369:
1.1 root 370: getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
371: so->so_fport = addr.sin_port;
1.1.1.7 root 372: if (addr.sin_addr.s_addr == 0 ||
373: addr.sin_addr.s_addr == loopback_addr.s_addr) {
374: so->so_faddr = slirp->vhost_addr;
375: } else {
1.1 root 376: so->so_faddr = addr.sin_addr;
1.1.1.7 root 377: }
1.1 root 378: so->so_lport = lport;
379: so->so_laddr.s_addr = laddr;
380: if (flags != SS_FACCEPTONCE)
381: so->so_expire = 0;
1.1.1.5 root 382:
1.1.1.7 root 383: so->so_state &= SS_PERSISTENT_MASK;
384: so->so_state |= SS_ISFCONNECTED | flags;
1.1.1.5 root 385:
1.1 root 386: return so;
387: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.