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

Defined functions

udp_ctlinput defined in line 149; used 2 times
udp_init defined in line 35; used 2 times
udp_input defined in line 49; used 2 times
udp_notify defined in line 141; used 1 times
udp_output defined in line 186; used 1 times
udp_usrreq defined in line 242; used 2 times

Defined variables

udp_in defined in line 47; used 3 times
udp_recvspace defined in line 239; used 1 times
udp_sendspace defined in line 238; used 1 times
udpcksum defined in line 44; used 2 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1816
Valid CSS Valid XHTML 1.0 Strict