# 2.11BSD#431 - /usr/src/sys/netinet/udp_usrreq.c

##### Functions

    udp_ctlinput      X
    udp_detach        X
    udp_init          X
    udp_input         X
    udp_notify        X
    udp_output        X
    udp_sysctl        X
    udp_usrreq        X

##### Variables

    udp_in            X
    udp_last_inpcb    X
    udp_recvspace     X
    udp_sendspace     X
    udpcksum          X

       1: /*
       2:  * Copyright (c) 1982, 1986 Regents of the University of California.
       3:  * All rights reserved.
       4:  *
       5:  * Redistribution and use in source and binary forms are permitted
       6:  * provided that this notice is preserved and that due credit is given
       7:  * to the University of California at Berkeley. The name of the University
       8:  * may not be used to endorse or promote products derived from this
       9:  * software without specific prior written permission. This software
      10:  * is provided ``as is'' without express or implied warranty.
      11:  *
      12:  *	@(#)udp_usrreq.c	7.5.2 (2.11BSD GTE) 1995/10/09
      13:  */
      14:
      15: #include "param.h"
      16: #include "user.h"
      17: #include "mbuf.h"
      18: #include "protosw.h"
      19: #include "socket.h"
      20: #include "socketvar.h"
      21: #include "errno.h"
      22:
      23: #include "../net/if.h"
      24: #include "../net/route.h"
      25:
      26: #include "domain.h"
      27: #include "in.h"
      28: #include "in_pcb.h"
      29: #include "in_systm.h"
      30: #include "ip.h"
      31: #include "ip_var.h"
      32: #include "ip_icmp.h"
      33: #include "udp.h"
      34: #include "udp_var.h"
      35:
      36: struct  inpcb *udp_last_inpcb = &udb;
      37:
      38: /*
      39:  * UDP protocol implementation.
      40:  * Per RFC 768, August, 1980.
      41:  */
      42: udp_init()
      43: {
      44:
      45:     udb.inp_next = udb.inp_prev = &udb;
      46: }
      47:
      48: #ifndef COMPAT_42
      49: int udpcksum = 1;
      50: #else
      51: int udpcksum = 0;       /* XXX */
      52: #endif
      53:
      54: struct  sockaddr_in udp_in = { AF_INET };
      55:
      56: udp_input(m0, ifp)
      57:     struct mbuf *m0;
      58:     struct ifnet *ifp;
      59: {
      60:     register struct udpiphdr *ui;
      61:     register struct inpcb *inp;
      62:     register struct mbuf *m;
      63:     int len;
      64:     struct ip ip;
      65:
      66:     udpstat.udps_ipackets++;
      67:
      68:     /*
      69: 	 * Get IP and UDP header together in first mbuf.
      70: 	 */
      71:     m = m0;
      72:     if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct udpiphdr)) &&
      73:         (m = m_pullup(m, sizeof (struct udpiphdr))) == 0) {
      74:         udpstat.udps_hdrops++;
      75:         return;
      76:     }
      77:     ui = mtod(m, struct udpiphdr *);
      78:     if (((struct ip *)ui)->ip_hl > (sizeof (struct ip) >> 2))
      79:         ip_stripoptions((struct ip *)ui, (struct mbuf *)0);
      80:
      81:     /*
      82: 	 * Make mbuf data length reflect UDP length.
      83: 	 * If not enough data to reflect UDP length, drop.
      84: 	 */
      85:     len = ntohs((u_short)ui->ui_ulen);
      86:     if (((struct ip *)ui)->ip_len != len) {
      87:         if (len > ((struct ip *)ui)->ip_len) {
      88:             udpstat.udps_badlen++;
      89:             goto bad;
      90:         }
      91:         m_adj(m, len - ((struct ip *)ui)->ip_len);
      92:         /* ((struct ip *)ui)->ip_len = len; */
      93:     }
      94:     /*
      95: 	 * Save a copy of the IP header in case we want restore it for ICMP.
      96: 	 */
      97:     ip = *(struct ip*)ui;
      98:
      99:     /*
     100: 	 * Checksum extended UDP header and data.
     101: 	 */
     102:     if (udpcksum && ui->ui_sum) {
     103:         ui->ui_next = ui->ui_prev = 0;
     104:         ui->ui_pad = 0;
     105:         ui->ui_x1 = 0;
     106:         ui->ui_len = ui->ui_ulen;
     107:         if (ui->ui_sum = in_cksum(m, len + sizeof (struct ip))) {
     108:             udpstat.udps_badsum++;
     109:             m_freem(m);
     110:             return;
     111:         }
     112:     }
     113:
     114:     /*
     115: 	 * Locate pcb for datagram.
     116: 	 */
     117:     inp = udp_last_inpcb;
     118:     if (inp->inp_lport != ui->ui_dport ||
     119:         inp->inp_fport != ui->ui_sport ||
     120:         inp->inp_faddr.s_addr != ui->ui_src.s_addr ||
     121:         inp->inp_laddr.s_addr != ui->ui_dst.s_addr) {
     122:         inp = in_pcblookup(&udb, ui->ui_src, ui->ui_sport,
     123:             ui->ui_dst, ui->ui_dport, INPLOOKUP_WILDCARD);
     124:         if (inp)
     125:             udp_last_inpcb = inp;
     126:         udpstat.udpps_pcbcachemiss++;
     127:     }
     128:     if (inp == 0) {
     129:         udpstat.udps_noport++;
     130:         /* don't send ICMP response for broadcast packet */
     131:         if (in_broadcast(ui->ui_dst)) {
     132:             udpstat.udps_noportbcast++;
     133:             goto bad;
     134:         }
     135:         *(struct ip *)ui = ip;
     136:         icmp_error((struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT,
     137:             ifp);
     138:         return;
     139:     }
     140:
     141:     /*
     142: 	 * Construct sockaddr format source address.
     143: 	 * Stuff source address and datagram in user buffer.
     144: 	 */
     145:     udp_in.sin_port = ui->ui_sport;
     146:     udp_in.sin_addr = ui->ui_src;
     147:     m->m_len -= sizeof (struct udpiphdr);
     148:     m->m_off += sizeof (struct udpiphdr);
     149:     if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
     150:         m, (struct mbuf *)0) == 0) {
     151:         udpstat.udps_fullsock++;
     152:         goto bad;
     153:     }
     154:     sorwakeup(inp->inp_socket);
     155:     return;
     156: bad:
     157:     m_freem(m);
     158: }
     159:
     160: /*
     161:  * Notify a udp user of an asynchronous error;
     162:  * just wake up so that he can collect error status.
     163:  */
     164: udp_notify(inp, errno)
     165:     register struct inpcb *inp;
     166:     int errno;
     167: {
     168:
     169:     inp->inp_socket->so_error = errno;
     170:     sorwakeup(inp->inp_socket);
     171:     sowwakeup(inp->inp_socket);
     172: }
     173:
     174: udp_ctlinput(cmd, sa, ip)
     175:     register int cmd;
     176:     struct sockaddr *sa;
     177:     register struct ip *ip;
     178: {
     179:     register struct udphdr *uh;
     180:     extern struct in_addr zeroin_addr;
     181:     extern u_char inetctlerrmap[];
     182:
     183:     if ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0)
     184:         return;
     185:     if (ip) {
     186:         uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
     187:         in_pcbnotify(&udb, sa, uh->uh_dport, ip->ip_src, uh->uh_sport,
     188:             cmd, udp_notify);
     189:     } else
     190:         in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify);
     191: }
     192:
     193: udp_output(inp, m0, addr, control)
     194:     register struct inpcb *inp;
     195:     struct mbuf *m0;
     196:     struct mbuf *addr, *control;
     197: {
     198:     register struct mbuf *m = m0;
     199:     register struct udpiphdr *ui;
     200:     register int len = 0;
     201:     struct in_addr laddr;
     202:     int s, error = 0;
     203:
     204:     if (addr) {
     205:         laddr = inp->inp_laddr;
     206:         if (inp->inp_faddr.s_addr != INADDR_ANY) {
     207:             error = EISCONN;
     208:             goto release;
     209:         }
     210:         /*
     211: 		 * Must block input while temporarily connected.
     212: 		 */
     213:         s = splnet();
     214:         error = in_pcbconnect(inp, addr);
     215:         if (error) {
     216:             splx(s);
     217:             goto release;
     218:         }
     219:     } else {
     220:         if (inp->inp_faddr.s_addr == INADDR_ANY) {
     221:             error = ENOTCONN;
     222:             goto release;
     223:         }
     224:     }
     225:
     226:     /*
     227: 	 * Calculate data length and get a mbuf
     228: 	 * for UDP and IP headers.
     229: 	 */
     230:     for (m = m0; m; m = m->m_next)
     231:         len += m->m_len;
     232:     MGET(m, M_WAIT, MT_HEADER);
     233:
     234:     /*
     235: 	 * Fill in mbuf with extended UDP header
     236: 	 * and addresses and length put into network format.
     237: 	 */
     238:     m->m_off = MMAXOFF - sizeof (struct udpiphdr);
     239:     m->m_len = sizeof (struct udpiphdr);
     240:     m->m_next = m0;
     241:     ui = mtod(m, struct udpiphdr *);
     242:     ui->ui_next = ui->ui_prev = 0;
     243:     ui->ui_pad = 0;
     244:     ui->ui_x1 = 0;
     245:     ui->ui_pr = IPPROTO_UDP;
     246:     ui->ui_len = htons((u_short)len + sizeof (struct udphdr));
     247:     ui->ui_src = inp->inp_laddr;
     248:     ui->ui_dst = inp->inp_faddr;
     249:     ui->ui_sport = inp->inp_lport;
     250:     ui->ui_dport = inp->inp_fport;
     251:     ui->ui_ulen = ui->ui_len;
     252:
     253:     /*
     254: 	 * Stuff checksum and output datagram.
     255: 	 */
     256:     ui->ui_sum = 0;
     257:     if (udpcksum) {
     258:         if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
     259:         ui->ui_sum = 0xffff;
     260:     }
     261:     ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
     262:     ((struct ip *)ui)->ip_ttl = ip_defttl;
     263:     udpstat.udps_opackets++;
     264:     error = ip_output(m, inp->inp_options, &inp->inp_route,
     265:         inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST));
     266:
     267:     if (addr) {
     268:         in_pcbdisconnect(inp);
     269:         inp->inp_laddr = laddr;
     270:         splx(s);
     271:     }
     272:     return(error);
     273:
     274: release:
     275:     m_freem(m);
     276:     return(error);
     277: }
     278:
     279: int udp_sendspace = 2048;       /* really max datagram size */
     280: int udp_recvspace = 4 * (1024+sizeof(struct sockaddr_in)); /* 4 1K dgrams */
     281:
     282: /*ARGSUSED*/
     283: udp_usrreq(so, req, m, nam, rights)
     284:     struct socket *so;
     285:     int req;
     286:     struct mbuf *m, *nam, *rights;
     287: {
     288:     register struct inpcb *inp = sotoinpcb(so);
     289:     int error = 0;
     290:     register int s;
     291:
     292:     if (req == PRU_CONTROL)
     293:         return (in_control(so, (int)m, (caddr_t)nam,
     294:             (struct ifnet *)rights));
     295:     if (rights && rights->m_len) {
     296:         error = EINVAL;
     297:         goto release;
     298:     }
     299:     if (inp == NULL && req != PRU_ATTACH) {
     300:         error = EINVAL;
     301:         goto release;
     302:     }
     303:     switch (req) {
     304:
     305:     case PRU_ATTACH:
     306:         if (inp != NULL) {
     307:             error = EINVAL;
     308:             break;
     309:         }
     310:         s = splnet();
     311:         error = in_pcballoc(so, &udb);
     312:         splx(s);
     313:         if (error)
     314:             break;
     315:         error = soreserve(so, udp_sendspace, udp_recvspace);
     316:         if (error)
     317:             break;
     318:         break;
     319:
     320:     case PRU_DETACH:
     321:         udp_detach(inp);
     322:         break;
     323:
     324:     case PRU_BIND:
     325:         s = splnet();
     326:         error = in_pcbbind(inp, nam);
     327:         splx(s);
     328:         break;
     329:
     330:     case PRU_LISTEN:
     331:         error = EOPNOTSUPP;
     332:         break;
     333:
     334:     case PRU_CONNECT:
     335:         if (inp->inp_faddr.s_addr != INADDR_ANY) {
     336:             error = EISCONN;
     337:             break;
     338:         }
     339:         s = splnet();
     340:         error = in_pcbconnect(inp, nam);
     341:         splx(s);
     342:         if (error == 0)
     343:             soisconnected(so);
     344:         break;
     345:
     346:     case PRU_CONNECT2:
     347:         error = EOPNOTSUPP;
     348:         break;
     349:
     350:     case PRU_ACCEPT:
     351:         error = EOPNOTSUPP;
     352:         break;
     353:
     354:     case PRU_DISCONNECT:
     355:         if (inp->inp_faddr.s_addr == INADDR_ANY) {
     356:             error = ENOTCONN;
     357:             break;
     358:         }
     359:         s = splnet();
     360:         in_pcbdisconnect(inp);
     361:         inp->inp_laddr.s_addr = INADDR_ANY;
     362:         splx(s);
     363:         so->so_state &= ~SS_ISCONNECTED;        /* XXX */
     364:         break;
     365:
     366:     case PRU_SHUTDOWN:
     367:         socantsendmore(so);
     368:         break;
     369:
     370:     case PRU_SEND:
     371:         return(udp_output(inp, m, nam, rights));
     372:
     373:     case PRU_ABORT:
     374:         soisdisconnected(so);
     375:         udp_detach(inp);
     376:         break;
     377:
     378:     case PRU_SOCKADDR:
     379:         in_setsockaddr(inp, nam);
     380:         break;
     381:
     382:     case PRU_PEERADDR:
     383:         in_setpeeraddr(inp, nam);
     384:         break;
     385:
     386:     case PRU_SENSE:
     387:         /*
     388: 		 * stat: don't bother with a blocksize.
     389: 		 */
     390:         return (0);
     391:
     392:     case PRU_SENDOOB:
     393:     case PRU_FASTTIMO:
     394:     case PRU_SLOWTIMO:
     395:     case PRU_PROTORCV:
     396:     case PRU_PROTOSEND:
     397:         error =  EOPNOTSUPP;
     398:         break;
     399:
     400:     case PRU_RCVD:
     401:     case PRU_RCVOOB:
     402:         return (EOPNOTSUPP);    /* do not free mbuf's */
     403:
     404:     default:
     405:         panic("udp_usrreq");
     406:     }
     407: release:
     408:     if (m != NULL)
     409:         m_freem(m);
     410:     return (error);
     411: }
     412:
     413: udp_detach(inp)
     414:     register struct inpcb *inp;
     415: {
     416:     register int s = splnet();
     417:
     418:     if (inp == udp_last_inpcb)
     419:         udp_last_inpcb = &udb;
     420:     in_pcbdetach(inp);
     421:     splx(s);
     422: }
     423:
     424: /*
     425:  * Sysctl for udp variables.
     426:  */
     427: udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
     428:     int *name;
     429:     u_int namelen;
     430:     void *oldp;
     431:     size_t *oldlenp;
     432:     void *newp;
     433:     size_t newlen;
     434: {
     435:     /* All sysctl names at this level are terminal. */
     436:     if (namelen != 1)
     437:         return (ENOTDIR);
     438:
     439:     switch (name[0]) {
     440:     case UDPCTL_CHECKSUM:
     441:         return (sysctl_int(oldp, oldlenp, newp, newlen, &udpcksum));
     442:     default:
     443:         return (ENOPROTOOPT);
     444:     }
     445:     /* NOTREACHED */
     446: }

#### Defined functions

udp_ctlinput defined in line 174; never used
udp_detach defined in line 413; used 2 times

- in line 321, 375

udp_init defined in line 42; never used
udp_input defined in line 56; never used
udp_notify defined in line 164; used 2 times

- in line 188-190(2)

udp_output defined in line 193; used 1 times

- in line 371

udp_sysctl defined in line 427; never used
udp_usrreq defined in line 283; never used

#### Defined variables

udp_in defined in line 54; used 3 times

- in line 145-149(3)

udp_last_inpcb defined in line 36; used 4 times

- in line 117, 125, 418-419(2)

udp_recvspace defined in line 280; used 1 times

- in line 315

udp_sendspace defined in line 279; used 1 times

- in line 315

udpcksum defined in line 51; used 3 times

- in line 102, 257, 441

Last modified: 1995-10-11 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2001 |