1 /* udp_usrreq.c 4.8 81/11/23 */ 2 3 #include "../h/param.h" 4 #include "../h/dir.h" 5 #include "../h/user.h" 6 #include "../h/mbuf.h" 7 #define PRUREQUESTS 8 #include "../h/protosw.h" 9 #include "../h/socket.h" 10 #include "../h/socketvar.h" 11 #include "../net/inet.h" 12 #include "../net/inet_pcb.h" 13 #include "../net/inet_systm.h" 14 #include "../net/ip.h" 15 #include "../net/ip_var.h" 16 #include "../net/udp.h" 17 #include "../net/udp_var.h" 18 19 /* 20 * UDP protocol implementation. 21 * Per RFC 768, August, 1980. 22 */ 23 udp_init() 24 { 25 26 udb.inp_next = udb.inp_prev = &udb; 27 } 28 29 int udpcksum; 30 struct sockaddr_in udp_in = { AF_INET }; 31 32 udp_input(m0) 33 struct mbuf *m0; 34 { 35 register struct udpiphdr *ui; 36 register struct inpcb *inp; 37 register struct mbuf *m; 38 int len, ulen; 39 40 /* 41 * Get ip and udp header together in first mbuf. 42 */ 43 printf("udp_input: "); 44 m = m0; 45 if (m->m_len < sizeof (struct udpiphdr) && 46 m_pullup(m, sizeof (struct udpiphdr)) == 0) { 47 udpstat.udps_hdrops++; 48 printf("hdrop m_len %d\n", m->m_len); 49 goto bad; 50 } 51 ui = mtod(m, struct udpiphdr *); 52 if (ui->ui_len > sizeof (struct ip)) 53 ip_stripoptions((struct ip *)ui, (char *)0); 54 55 /* 56 * Make mbuf data length reflect udp length. 57 * If not enough data to reflect udp length, drop. 58 */ 59 ulen = ntohs((u_short)ui->ui_ulen); 60 len = sizeof (struct udpiphdr) + ulen; 61 printf("ulen %d, len %d\n", ulen, len); 62 if (((struct ip *)ui)->ip_len != len) { 63 if (len > ((struct ip *)ui)->ip_len) { 64 printf("udp badlen\n"); 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)(sizeof (struct udpiphdr) + ulen)); 79 if ((ui->ui_sum = inet_cksum(m, len)) != 0xffff) { 80 udpstat.udps_badsum++; 81 printf("udp cksum %x\n", ui->ui_sum); 82 m_freem(m); 83 return; 84 } 85 } 86 87 /* 88 * Convert addresses and ports to host format. 89 * Locate pcb for datagram. 90 */ 91 printf("src %x dst %x sport %x dport %x\n", 92 ui->ui_src.s_addr, ui->ui_dst.s_addr, ui->ui_sport, ui->ui_dport); 93 inp = in_pcblookup(&udb, 94 ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport); 95 if (inp == 0) { 96 printf("pcb not found\n"); 97 goto bad; 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, m) == 0) 109 goto bad; 110 sorwakeup(inp->inp_socket); 111 return; 112 bad: 113 m_freem(m); 114 } 115 116 udp_ctlinput(m) 117 struct mbuf *m; 118 { 119 120 printf("udp_ctlinput\n"); 121 m_freem(m); 122 } 123 124 /*ARGSUSED*/ 125 udp_output(inp, m0) 126 struct inpcb *inp; 127 struct mbuf *m0; 128 { 129 register struct mbuf *m; 130 register struct udpiphdr *ui; 131 register int len = 0; 132 133 /* 134 * Calculate data length and get a mbuf 135 * for udp and ip headers. 136 */ 137 for (m = m0; m; m = m->m_next) 138 len += m->m_len; 139 printf("udp_output len %d: ", len); 140 m = m_get(0); 141 if (m == 0) { 142 printf("no mbufs\n"); 143 goto bad; 144 } 145 146 /* 147 * Fill in mbuf with extended udp header 148 * and addresses and length put into network format. 149 */ 150 m->m_off = MMAXOFF - sizeof (struct udpiphdr); 151 m->m_len = sizeof (struct udpiphdr); 152 m->m_next = m0; 153 ui = mtod(m, struct udpiphdr *); 154 ui->ui_next = ui->ui_prev = 0; 155 ui->ui_x1 = 0; 156 ui->ui_pr = IPPROTO_UDP; 157 ui->ui_len = sizeof (struct udpiphdr) + len; 158 ui->ui_src = inp->inp_laddr; 159 ui->ui_dst = inp->inp_faddr; 160 ui->ui_sport = inp->inp_lport; 161 ui->ui_dport = inp->inp_fport; 162 ui->ui_ulen = htons((u_short)len); 163 printf("src %x dst %x sport %x dport %x", 164 ui->ui_src.s_addr, ui->ui_dst.s_addr, ui->ui_sport, ui->ui_dport); 165 166 /* 167 * Stuff checksum and output datagram. 168 */ 169 ui->ui_sum = 0; 170 ui->ui_sum = inet_cksum(m, sizeof (struct udpiphdr) + len); 171 printf(" cksum %x\n", ui->ui_sum); 172 ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; 173 ((struct ip *)ui)->ip_ttl = MAXTTL; 174 ip_output(m); 175 return; 176 bad: 177 m_freem(m); 178 } 179 180 /*ARGSUSED*/ 181 udp_usrreq(so, req, m, addr) 182 struct socket *so; 183 int req; 184 struct mbuf *m; 185 caddr_t addr; 186 { 187 struct inpcb *inp = sotoinpcb(so); 188 int error; 189 190 printf("udp_usrreq %x %s\n", inp, prurequests[req]); 191 if (inp == 0 && req != PRU_ATTACH) { 192 printf("inp == 0 not on ATTACH\n"); 193 return (EINVAL); 194 } 195 switch (req) { 196 197 case PRU_ATTACH: 198 if (inp != 0) 199 return (EINVAL); 200 error = in_pcballoc(so, &udb, 2048, 2048, (struct sockaddr_in *)addr); 201 if (error) { 202 printf("in_pcballoc failed %d\n", error); 203 return (error); 204 } 205 break; 206 207 case PRU_DETACH: 208 if (inp == 0) 209 return (ENOTCONN); 210 in_pcbfree(inp); 211 break; 212 213 case PRU_CONNECT: 214 if (inp->inp_faddr.s_addr) 215 return (EISCONN); 216 error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr); 217 if (error) { 218 printf("in_pcbsetpeer failed %d\n", error); 219 return (error); 220 } 221 soisconnected(so); 222 break; 223 224 case PRU_ACCEPT: 225 return (EOPNOTSUPP); 226 227 case PRU_DISCONNECT: 228 if (inp->inp_faddr.s_addr == 0) 229 return (ENOTCONN); 230 inp->inp_faddr.s_addr = 0; 231 soisdisconnected(so); 232 break; 233 234 case PRU_SHUTDOWN: 235 socantsendmore(so); 236 break; 237 238 case PRU_SEND: 239 if (addr) { 240 if (inp->inp_faddr.s_addr) 241 return (EISCONN); 242 error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr); 243 if (error) { 244 printf("send setpeer failed %d\n", error); 245 return (error); 246 } 247 } else { 248 if (inp->inp_faddr.s_addr == 0) 249 return (ENOTCONN); 250 } 251 printf("udp send m %x m_len %d * %c (%o)\n", 252 m, m->m_len, *(mtod(m, caddr_t)), *(mtod(m, caddr_t))); 253 udp_output(inp, m); 254 if (addr) 255 inp->inp_faddr.s_addr = 0; 256 break; 257 258 case PRU_ABORT: 259 in_pcbfree(inp); 260 sofree(so); 261 soisdisconnected(so); 262 break; 263 264 case PRU_CONTROL: 265 return (EOPNOTSUPP); 266 267 default: 268 panic("udp_usrreq"); 269 } 270 return (0); 271 } 272 273 /*ARGSUSED*/ 274 udp_sense(m) 275 struct mbuf *m; 276 { 277 278 printf("udp_sense\n"); 279 return (EOPNOTSUPP); 280 } 281