|
|
1.1 ! root 1: /* udp_usrreq.c 6.1 83/07/29 */ ! 2: ! 3: #include "../h/param.h" ! 4: #include "../h/dir.h" ! 5: #include "../h/user.h" ! 6: #include "../h/mbuf.h" ! 7: #include "../h/protosw.h" ! 8: #include "../h/socket.h" ! 9: #include "../h/socketvar.h" ! 10: #include "../h/errno.h" ! 11: ! 12: #include "../net/if.h" ! 13: #include "../net/route.h" ! 14: ! 15: #include "../netinet/in.h" ! 16: #include "../netinet/in_pcb.h" ! 17: #include "../netinet/in_systm.h" ! 18: #include "../netinet/ip.h" ! 19: #include "../netinet/ip_var.h" ! 20: #include "../netinet/ip_icmp.h" ! 21: #include "../netinet/udp.h" ! 22: #include "../netinet/udp_var.h" ! 23: ! 24: #ifdef UDPPRINTFS ! 25: int udpprintfs = 0; ! 26: #endif ! 27: ! 28: /* ! 29: * Changes in udp_usrreq() ! 30: * ! 31: * PRU_OOB mark mbuf not to be deallocated for PRU_OOB (soreceive() ! 32: * will). ! 33: * ! 34: * PRU_ABORT disconnect the socket first before detaching its ! 35: * pcb. also comment out socket deallocation as ! 36: * in_pcbdetach() already did. ! 37: * ! 38: * PRU_ATTACH reverse the sequence: soreserve() before ! 39: * in_pcballoc(). Otherwise, if soreserve() fails, ! 40: * allocated mbufs are not returned to free pool. ! 41: * ! 42: */ ! 43: /* ! 44: * UDP protocol implementation. ! 45: * Per RFC 768, August, 1980. ! 46: */ ! 47: udp_init() ! 48: { ! 49: ! 50: udb.inp_next = udb.inp_prev = &udb; ! 51: } ! 52: ! 53: int udpcksum; ! 54: struct sockaddr_in udp_in = { AF_INET }; ! 55: ! 56: udp_input(m0) ! 57: struct mbuf *m0; ! 58: { ! 59: register struct udpiphdr *ui; ! 60: register struct inpcb *inp; ! 61: register struct mbuf *m; ! 62: int len; ! 63: ! 64: /* ! 65: * Get IP and UDP header together in first mbuf. ! 66: */ ! 67: m = m0; ! 68: if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct udpiphdr)) && ! 69: (m = m_pullup(m, sizeof (struct udpiphdr))) == 0) { ! 70: udpstat.udps_hdrops++; ! 71: return; ! 72: } ! 73: ui = mtod(m, struct udpiphdr *); ! 74: if (((struct ip *)ui)->ip_hl > (sizeof (struct ip) >> 2)) ! 75: ip_stripoptions((struct ip *)ui, (struct mbuf *)0); ! 76: ! 77: /* ! 78: * Make mbuf data length reflect UDP length. ! 79: * If not enough data to reflect UDP length, drop. ! 80: */ ! 81: len = ntohs((u_short)ui->ui_ulen); ! 82: if (((struct ip *)ui)->ip_len != len) { ! 83: if (len > ((struct ip *)ui)->ip_len) { ! 84: udpstat.udps_badlen++; ! 85: goto bad; ! 86: } ! 87: m_adj(m, ((struct ip *)ui)->ip_len - len); ! 88: /* (struct ip *)ui->ip_len = len; */ ! 89: } ! 90: ! 91: /* ! 92: * Checksum extended UDP header and data. ! 93: */ ! 94: if (udpcksum) { ! 95: ui->ui_next = ui->ui_prev = 0; ! 96: ui->ui_x1 = 0; ! 97: ui->ui_len = htons((u_short)len); ! 98: if (ui->ui_sum = in_cksum(m, len + sizeof (struct ip))) { ! 99: udpstat.udps_badsum++; ! 100: m_freem(m); ! 101: return; ! 102: } ! 103: } ! 104: ! 105: /* ! 106: * Locate pcb for datagram. ! 107: */ ! 108: inp = in_pcblookup(&udb, ! 109: ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport, ! 110: INPLOOKUP_WILDCARD); ! 111: if (inp == 0) { ! 112: #ifdef UDPPRINTFS ! 113: if (udpprintfs) ! 114: printf("udp_input:udb %x, src %x, sport %d, dst %x, dport %d\n", ! 115: &udb, ui->ui_src, ui->ui_sport, ! 116: ui->ui_dst, ui->ui_dport); ! 117: #endif ! 118: /* don't send ICMP response for broadcast packet */ ! 119: if (in_lnaof(ui->ui_dst) == INADDR_ANY) ! 120: goto bad; ! 121: icmp_error((struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT); ! 122: return; ! 123: } ! 124: ! 125: /* ! 126: * Construct sockaddr format source address. ! 127: * Stuff source address and datagram in user buffer. ! 128: */ ! 129: udp_in.sin_port = ui->ui_sport; ! 130: udp_in.sin_addr = ui->ui_src; ! 131: m->m_len -= sizeof (struct udpiphdr); ! 132: m->m_off += sizeof (struct udpiphdr); ! 133: if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, ! 134: m, (struct mbuf *)0) == 0) ! 135: goto bad; ! 136: sorwakeup(inp->inp_socket); ! 137: return; ! 138: bad: ! 139: m_freem(m); ! 140: } ! 141: ! 142: udp_abort(inp) ! 143: struct inpcb *inp; ! 144: { ! 145: struct socket *so = inp->inp_socket; ! 146: ! 147: in_pcbdisconnect(inp); ! 148: soisdisconnected(so); ! 149: } ! 150: ! 151: udp_ctlinput(cmd, arg) ! 152: int cmd; ! 153: caddr_t arg; ! 154: { ! 155: struct in_addr *sin; ! 156: extern u_char inetctlerrmap[]; ! 157: ! 158: if (cmd < 0 || cmd > PRC_NCMDS) ! 159: return; ! 160: switch (cmd) { ! 161: ! 162: case PRC_ROUTEDEAD: ! 163: break; ! 164: ! 165: case PRC_QUENCH: ! 166: break; ! 167: ! 168: /* these are handled by ip */ ! 169: case PRC_IFDOWN: ! 170: case PRC_HOSTDEAD: ! 171: case PRC_HOSTUNREACH: ! 172: break; ! 173: ! 174: default: ! 175: sin = &((struct icmp *)arg)->icmp_ip.ip_dst; ! 176: in_pcbnotify(&udb, sin, (int)inetctlerrmap[cmd], udp_abort); ! 177: } ! 178: } ! 179: ! 180: udp_output(inp, m0) ! 181: struct inpcb *inp; ! 182: struct mbuf *m0; ! 183: { ! 184: register struct mbuf *m; ! 185: register struct udpiphdr *ui; ! 186: register struct socket *so; ! 187: register int len = 0; ! 188: int flags; ! 189: ! 190: /* ! 191: * Calculate data length and get a mbuf ! 192: * for UDP and IP headers. ! 193: */ ! 194: for (m = m0; m; m = m->m_next) ! 195: len += m->m_len; ! 196: m = m_get(M_DONTWAIT, MT_HEADER); ! 197: MBUFNULL(17, m); /* for debugging */ ! 198: if (m == 0) { ! 199: m_freem(m0); ! 200: return (ENOBUFS); ! 201: } ! 202: ! 203: /* ! 204: * Fill in mbuf with extended UDP header ! 205: * and addresses and length put into network format. ! 206: */ ! 207: m->m_off = MMAXOFF - sizeof (struct udpiphdr); ! 208: m->m_len = sizeof (struct udpiphdr); ! 209: m->m_next = m0; ! 210: ui = mtod(m, struct udpiphdr *); ! 211: ui->ui_next = ui->ui_prev = 0; ! 212: ui->ui_x1 = 0; ! 213: ui->ui_pr = IPPROTO_UDP; ! 214: ui->ui_len = len + sizeof (struct udphdr); ! 215: ui->ui_src = inp->inp_laddr; ! 216: ui->ui_dst = inp->inp_faddr; ! 217: ui->ui_sport = inp->inp_lport; ! 218: ui->ui_dport = inp->inp_fport; ! 219: ui->ui_ulen = htons((u_short)ui->ui_len); ! 220: ! 221: /* ! 222: * Stuff checksum and output datagram. ! 223: */ ! 224: ui->ui_sum = 0; ! 225: ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len); ! 226: ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; ! 227: ((struct ip *)ui)->ip_ttl = MAXTTL; ! 228: so = inp->inp_socket; ! 229: flags = (so->so_options & SO_DONTROUTE) | (so->so_state & SS_PRIV); ! 230: return (ip_output(m, (struct mbuf *)0, (struct route *)0, flags)); ! 231: } ! 232: ! 233: /*ARGSUSED*/ ! 234: udp_usrreq(so, req, m, nam, rights) ! 235: struct socket *so; ! 236: int req; ! 237: struct mbuf *m, *nam, *rights; ! 238: { ! 239: struct inpcb *inp = sotoinpcb(so); ! 240: int error = 0; ! 241: ! 242: if (rights && rights->m_len) { ! 243: error = EINVAL; ! 244: goto release; ! 245: } ! 246: if (inp == NULL && req != PRU_ATTACH) { ! 247: error = EINVAL; ! 248: goto release; ! 249: } ! 250: switch (req) { ! 251: ! 252: case PRU_ATTACH: ! 253: if (inp != NULL) { ! 254: error = EINVAL; ! 255: break; ! 256: } ! 257: error = soreserve(so, 2048, 2048); ! 258: if (error) ! 259: break; ! 260: error = in_pcballoc(so, &udb); ! 261: if (error) ! 262: break; ! 263: break; ! 264: ! 265: case PRU_DETACH: ! 266: if (inp == NULL) { ! 267: error = ENOTCONN; ! 268: break; ! 269: } ! 270: in_pcbdetach(inp); ! 271: break; ! 272: ! 273: case PRU_BIND: ! 274: error = in_pcbbind(inp, nam); ! 275: break; ! 276: ! 277: case PRU_LISTEN: ! 278: error = EOPNOTSUPP; ! 279: break; ! 280: ! 281: case PRU_CONNECT: ! 282: if (inp->inp_faddr.s_addr != INADDR_ANY) { ! 283: error = EISCONN; ! 284: break; ! 285: } ! 286: error = in_pcbconnect(inp, nam); ! 287: if (error == 0) ! 288: soisconnected(so); ! 289: break; ! 290: ! 291: case PRU_CONNECT2: ! 292: error = EOPNOTSUPP; ! 293: break; ! 294: ! 295: case PRU_ACCEPT: ! 296: error = EOPNOTSUPP; ! 297: break; ! 298: ! 299: case PRU_DISCONNECT: ! 300: if (inp->inp_faddr.s_addr == INADDR_ANY) { ! 301: error = ENOTCONN; ! 302: break; ! 303: } ! 304: in_pcbdisconnect(inp); ! 305: soisdisconnected(so); ! 306: break; ! 307: ! 308: case PRU_SHUTDOWN: ! 309: socantsendmore(so); ! 310: break; ! 311: ! 312: case PRU_SEND: { ! 313: struct in_addr laddr; ! 314: ! 315: if (nam) { ! 316: laddr = inp->inp_laddr; ! 317: if (inp->inp_faddr.s_addr != INADDR_ANY) { ! 318: error = EISCONN; ! 319: break; ! 320: } ! 321: error = in_pcbconnect(inp, nam); ! 322: if (error) ! 323: break; ! 324: } else { ! 325: if (inp->inp_faddr.s_addr == INADDR_ANY) { ! 326: error = ENOTCONN; ! 327: break; ! 328: } ! 329: } ! 330: error = udp_output(inp, m); ! 331: m = NULL; ! 332: if (nam) { ! 333: in_pcbdisconnect(inp); ! 334: inp->inp_laddr = laddr; ! 335: } ! 336: } ! 337: break; ! 338: ! 339: case PRU_ABORT: ! 340: soisdisconnected(so); ! 341: in_pcbdetach(inp); ! 342: /* sofree(so); */ ! 343: break; ! 344: ! 345: case PRU_SOCKADDR: ! 346: in_setsockaddr(inp, nam); ! 347: break; ! 348: ! 349: case PRU_PEERADDR: ! 350: in_setpeeraddr(inp, nam); ! 351: break; ! 352: ! 353: case PRU_CONTROL: ! 354: m = NULL; ! 355: error = EOPNOTSUPP; ! 356: break; ! 357: ! 358: case PRU_SENSE: ! 359: case PRU_RCVOOB: ! 360: m = NULL; ! 361: /* fall thru... */ ! 362: ! 363: case PRU_RCVD: ! 364: case PRU_SENDOOB: ! 365: case PRU_FASTTIMO: ! 366: case PRU_SLOWTIMO: ! 367: case PRU_PROTORCV: ! 368: case PRU_PROTOSEND: ! 369: error = EOPNOTSUPP; ! 370: break; ! 371: ! 372: default: ! 373: panic("udp_usrreq"); ! 374: } ! 375: release: ! 376: if (m != NULL) ! 377: m_freem(m); ! 378: return (error); ! 379: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.