Annotation of qemu/slirp/udp.c, revision 1.1.1.10

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.