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

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.11! root       52: 
        !            53: void udp_cleanup(Slirp *slirp)
        !            54: {
        !            55:     while (slirp->udb.so_next != &slirp->udb) {
        !            56:         udp_detach(slirp->udb.so_next);
        !            57:     }
        !            58: }
        !            59: 
1.1.1.5   root       60: /* m->m_data  points at ip packet header
                     61:  * m->m_len   length ip packet
1.1       root       62:  * ip->ip_len length data (IPDU)
                     63:  */
                     64: void
1.1.1.7   root       65: udp_input(register struct mbuf *m, int iphlen)
1.1       root       66: {
1.1.1.7   root       67:        Slirp *slirp = m->slirp;
1.1       root       68:        register struct ip *ip;
                     69:        register struct udphdr *uh;
                     70:        int len;
1.1.1.5   root       71:        struct ip save_ip;
1.1       root       72:        struct socket *so;
1.1.1.5   root       73: 
1.1       root       74:        DEBUG_CALL("udp_input");
                     75:        DEBUG_ARG("m = %lx", (long)m);
                     76:        DEBUG_ARG("iphlen = %d", iphlen);
1.1.1.5   root       77: 
1.1       root       78:        /*
                     79:         * Strip IP options, if any; should skip this,
                     80:         * make available to user, and use on returned packets,
                     81:         * but we don't yet have a way to check the checksum
                     82:         * with options still present.
                     83:         */
                     84:        if(iphlen > sizeof(struct ip)) {
                     85:                ip_stripoptions(m, (struct mbuf *)0);
                     86:                iphlen = sizeof(struct ip);
                     87:        }
                     88: 
                     89:        /*
                     90:         * Get IP and UDP header together in first mbuf.
                     91:         */
                     92:        ip = mtod(m, struct ip *);
                     93:        uh = (struct udphdr *)((caddr_t)ip + iphlen);
                     94: 
                     95:        /*
                     96:         * Make mbuf data length reflect UDP length.
                     97:         * If not enough data to reflect UDP length, drop.
                     98:         */
1.1.1.9   root       99:        len = ntohs((uint16_t)uh->uh_ulen);
1.1       root      100: 
                    101:        if (ip->ip_len != len) {
                    102:                if (len > ip->ip_len) {
                    103:                        goto bad;
                    104:                }
                    105:                m_adj(m, len - ip->ip_len);
                    106:                ip->ip_len = len;
                    107:        }
1.1.1.5   root      108: 
1.1       root      109:        /*
                    110:         * Save a copy of the IP header in case we want restore it
                    111:         * for sending an ICMP error message in response.
                    112:         */
1.1.1.5   root      113:        save_ip = *ip;
1.1       root      114:        save_ip.ip_len+= iphlen;         /* tcp_input subtracts this */
                    115: 
                    116:        /*
                    117:         * Checksum extended UDP header and data.
                    118:         */
1.1.1.7   root      119:        if (uh->uh_sum) {
1.1.1.6   root      120:       memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr));
1.1       root      121:          ((struct ipovly *)ip)->ih_x1 = 0;
                    122:          ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
                    123:          if(cksum(m, len + sizeof(struct ip))) {
                    124:            goto bad;
                    125:          }
                    126:        }
                    127: 
                    128:         /*
                    129:          *  handle DHCP/BOOTP
                    130:          */
1.1.1.10  root      131:         if (ntohs(uh->uh_dport) == BOOTP_SERVER &&
                    132:             (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr ||
                    133:              ip->ip_dst.s_addr == 0xffffffff)) {
                    134:                 bootp_input(m);
                    135:                 goto bad;
                    136:             }
1.1.1.6   root      137: 
1.1       root      138:         /*
                    139:          *  handle TFTP
                    140:          */
1.1.1.10  root      141:         if (ntohs(uh->uh_dport) == TFTP_SERVER &&
                    142:             ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {
1.1       root      143:             tftp_input(m);
                    144:             goto bad;
                    145:         }
                    146: 
1.1.1.10  root      147:         if (slirp->restricted) {
                    148:             goto bad;
                    149:         }
                    150: 
1.1       root      151:        /*
                    152:         * Locate pcb for datagram.
                    153:         */
1.1.1.7   root      154:        so = slirp->udp_last_so;
1.1       root      155:        if (so->so_lport != uh->uh_sport ||
                    156:            so->so_laddr.s_addr != ip->ip_src.s_addr) {
                    157:                struct socket *tmp;
1.1.1.5   root      158: 
1.1.1.7   root      159:                for (tmp = slirp->udb.so_next; tmp != &slirp->udb;
                    160:                     tmp = tmp->so_next) {
1.1       root      161:                        if (tmp->so_lport == uh->uh_sport &&
                    162:                            tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
                    163:                                so = tmp;
                    164:                                break;
                    165:                        }
                    166:                }
1.1.1.7   root      167:                if (tmp == &slirp->udb) {
1.1       root      168:                  so = NULL;
                    169:                } else {
1.1.1.7   root      170:                  slirp->udp_last_so = so;
1.1       root      171:                }
                    172:        }
1.1.1.5   root      173: 
1.1       root      174:        if (so == NULL) {
                    175:          /*
                    176:           * If there's no socket for this packet,
                    177:           * create one
                    178:           */
1.1.1.7   root      179:          so = socreate(slirp);
                    180:          if (!so) {
                    181:              goto bad;
                    182:          }
1.1       root      183:          if(udp_attach(so) == -1) {
1.1.1.5   root      184:            DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
1.1       root      185:                        errno,strerror(errno)));
                    186:            sofree(so);
                    187:            goto bad;
                    188:          }
1.1.1.5   root      189: 
1.1       root      190:          /*
                    191:           * Setup fields
                    192:           */
                    193:          so->so_laddr = ip->ip_src;
                    194:          so->so_lport = uh->uh_sport;
1.1.1.5   root      195: 
1.1       root      196:          if ((so->so_iptos = udp_tos(so)) == 0)
                    197:            so->so_iptos = ip->ip_tos;
1.1.1.5   root      198: 
1.1       root      199:          /*
                    200:           * XXXXX Here, check if it's in udpexec_list,
                    201:           * and if it is, do the fork_exec() etc.
                    202:           */
                    203:        }
                    204: 
1.1.1.4   root      205:         so->so_faddr = ip->ip_dst; /* XXX */
                    206:         so->so_fport = uh->uh_dport; /* XXX */
                    207: 
1.1       root      208:        iphlen += sizeof(struct udphdr);
                    209:        m->m_len -= iphlen;
                    210:        m->m_data += iphlen;
                    211: 
                    212:        /*
                    213:         * Now we sendto() the packet.
                    214:         */
                    215:        if(sosendto(so,m) == -1) {
                    216:          m->m_len += iphlen;
                    217:          m->m_data -= iphlen;
                    218:          *ip=save_ip;
                    219:          DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
1.1.1.5   root      220:          icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
1.1       root      221:        }
                    222: 
                    223:        m_free(so->so_m);   /* used for ICMP if error on sorecvfrom */
                    224: 
                    225:        /* restore the orig mbuf packet */
                    226:        m->m_len += iphlen;
                    227:        m->m_data -= iphlen;
                    228:        *ip=save_ip;
                    229:        so->so_m=m;         /* ICMP backup */
                    230: 
                    231:        return;
                    232: bad:
1.1.1.10  root      233:        m_free(m);
1.1       root      234:        return;
                    235: }
                    236: 
1.1.1.5   root      237: int udp_output2(struct socket *so, struct mbuf *m,
1.1       root      238:                 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
                    239:                 int iptos)
                    240: {
                    241:        register struct udpiphdr *ui;
                    242:        int error = 0;
                    243: 
                    244:        DEBUG_CALL("udp_output");
                    245:        DEBUG_ARG("so = %lx", (long)so);
                    246:        DEBUG_ARG("m = %lx", (long)m);
                    247:        DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr);
                    248:        DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr);
                    249: 
                    250:        /*
                    251:         * Adjust for header
                    252:         */
                    253:        m->m_data -= sizeof(struct udpiphdr);
                    254:        m->m_len += sizeof(struct udpiphdr);
1.1.1.5   root      255: 
1.1       root      256:        /*
                    257:         * Fill in mbuf with extended UDP header
                    258:         * and addresses and length put into network format.
                    259:         */
                    260:        ui = mtod(m, struct udpiphdr *);
1.1.1.6   root      261:     memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
1.1       root      262:        ui->ui_x1 = 0;
                    263:        ui->ui_pr = IPPROTO_UDP;
1.1.1.7   root      264:        ui->ui_len = htons(m->m_len - sizeof(struct ip));
1.1       root      265:        /* XXXXX Check for from-one-location sockets, or from-any-location sockets */
                    266:         ui->ui_src = saddr->sin_addr;
                    267:        ui->ui_dst = daddr->sin_addr;
                    268:        ui->ui_sport = saddr->sin_port;
                    269:        ui->ui_dport = daddr->sin_port;
                    270:        ui->ui_ulen = ui->ui_len;
                    271: 
                    272:        /*
                    273:         * Stuff checksum and output datagram.
                    274:         */
                    275:        ui->ui_sum = 0;
1.1.1.7   root      276:        if ((ui->ui_sum = cksum(m, m->m_len)) == 0)
1.1       root      277:                ui->ui_sum = 0xffff;
                    278:        ((struct ip *)ui)->ip_len = m->m_len;
                    279: 
1.1.1.5   root      280:        ((struct ip *)ui)->ip_ttl = IPDEFTTL;
1.1       root      281:        ((struct ip *)ui)->ip_tos = iptos;
1.1.1.5   root      282: 
1.1       root      283:        error = ip_output(so, m);
1.1.1.5   root      284: 
1.1       root      285:        return (error);
                    286: }
                    287: 
1.1.1.5   root      288: int udp_output(struct socket *so, struct mbuf *m,
1.1       root      289:                struct sockaddr_in *addr)
                    290: 
                    291: {
1.1.1.7   root      292:     Slirp *slirp = so->slirp;
1.1       root      293:     struct sockaddr_in saddr, daddr;
                    294: 
                    295:     saddr = *addr;
1.1.1.7   root      296:     if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
                    297:         slirp->vnetwork_addr.s_addr) {
                    298:         uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr;
                    299: 
                    300:         if ((so->so_faddr.s_addr & inv_mask) == inv_mask) {
                    301:             saddr.sin_addr = slirp->vhost_addr;
                    302:         } else if (addr->sin_addr.s_addr == loopback_addr.s_addr ||
                    303:                    so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
                    304:             saddr.sin_addr = so->so_faddr;
                    305:         }
1.1.1.3   root      306:     }
1.1       root      307:     daddr.sin_addr = so->so_laddr;
                    308:     daddr.sin_port = so->so_lport;
1.1.1.5   root      309: 
1.1       root      310:     return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
                    311: }
                    312: 
                    313: int
1.1.1.7   root      314: udp_attach(struct socket *so)
1.1       root      315: {
1.1.1.8   root      316:   if((so->s = qemu_socket(AF_INET,SOCK_DGRAM,0)) != -1) {
                    317:     so->so_expire = curtime + SO_EXPIRE;
                    318:     insque(so, &so->slirp->udb);
1.1       root      319:   }
                    320:   return(so->s);
                    321: }
                    322: 
                    323: void
1.1.1.7   root      324: udp_detach(struct socket *so)
1.1       root      325: {
                    326:        closesocket(so->s);
                    327:        sofree(so);
                    328: }
                    329: 
1.1.1.5   root      330: static const struct tos_t udptos[] = {
1.1       root      331:        {0, 53, IPTOS_LOWDELAY, 0},                     /* DNS */
                    332:        {0, 0, 0, 0}
                    333: };
                    334: 
1.1.1.9   root      335: static uint8_t
1.1.1.5   root      336: udp_tos(struct socket *so)
1.1       root      337: {
                    338:        int i = 0;
1.1.1.5   root      339: 
1.1       root      340:        while(udptos[i].tos) {
                    341:                if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
                    342:                    (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
                    343:                        so->so_emu = udptos[i].emu;
                    344:                        return udptos[i].tos;
                    345:                }
                    346:                i++;
                    347:        }
1.1.1.5   root      348: 
1.1       root      349:        return 0;
                    350: }
                    351: 
                    352: struct socket *
1.1.1.9   root      353: udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
1.1.1.7   root      354:            u_int lport, int flags)
1.1       root      355: {
                    356:        struct sockaddr_in addr;
                    357:        struct socket *so;
1.1.1.6   root      358:        socklen_t addrlen = sizeof(struct sockaddr_in), opt = 1;
1.1.1.5   root      359: 
1.1.1.7   root      360:        so = socreate(slirp);
                    361:        if (!so) {
                    362:            return NULL;
1.1       root      363:        }
1.1.1.8   root      364:        so->s = qemu_socket(AF_INET,SOCK_DGRAM,0);
1.1       root      365:        so->so_expire = curtime + SO_EXPIRE;
1.1.1.7   root      366:        insque(so, &slirp->udb);
1.1       root      367: 
                    368:        addr.sin_family = AF_INET;
1.1.1.7   root      369:        addr.sin_addr.s_addr = haddr;
                    370:        addr.sin_port = hport;
1.1       root      371: 
                    372:        if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
                    373:                udp_detach(so);
                    374:                return NULL;
                    375:        }
                    376:        setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
1.1.1.5   root      377: 
1.1       root      378:        getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
                    379:        so->so_fport = addr.sin_port;
1.1.1.7   root      380:        if (addr.sin_addr.s_addr == 0 ||
                    381:            addr.sin_addr.s_addr == loopback_addr.s_addr) {
                    382:           so->so_faddr = slirp->vhost_addr;
                    383:        } else {
1.1       root      384:           so->so_faddr = addr.sin_addr;
1.1.1.7   root      385:        }
1.1       root      386:        so->so_lport = lport;
                    387:        so->so_laddr.s_addr = laddr;
                    388:        if (flags != SS_FACCEPTONCE)
                    389:           so->so_expire = 0;
1.1.1.5   root      390: 
1.1.1.7   root      391:        so->so_state &= SS_PERSISTENT_MASK;
                    392:        so->so_state |= SS_ISFCONNECTED | flags;
1.1.1.5   root      393: 
1.1       root      394:        return so;
                    395: }

unix.superglobalmegacorp.com

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