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