1 /* udp_usrreq.c 4.15 81/12/09 */ 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 "../net/in.h" 11 #include "../net/in_pcb.h" 12 #include "../net/in_systm.h" 13 #include "../net/ip.h" 14 #include "../net/ip_var.h" 15 #include "../net/udp.h" 16 #include "../net/udp_var.h" 17 18 /* 19 * UDP protocol implementation. 20 * Per RFC 768, August, 1980. 21 */ 22 udp_init() 23 { 24 25 COUNT(UDP_INIT); 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 COUNT(UDP_INPUT); 41 /* 42 * Get ip and udp header together in first mbuf. 43 */ 44 m = m0; 45 if (m->m_len < sizeof (struct udpiphdr) && 46 m_pullup(m, sizeof (struct udpiphdr)) == 0) { 47 udpstat.udps_hdrops++; 48 goto bad; 49 } 50 ui = mtod(m, struct udpiphdr *); 51 if (ui->ui_len > sizeof (struct ip)) 52 ip_stripoptions((struct ip *)ui, (struct mbuf *)0); 53 54 /* 55 * Make mbuf data length reflect udp length. 56 * If not enough data to reflect udp length, drop. 57 */ 58 ulen = ntohs((u_short)ui->ui_ulen); 59 len = sizeof (struct udphdr) + ulen; 60 printf("len %d, ulen %d, ((struct ip *)ui)->ip_len %d\n", 61 len, ulen, ((struct ip *)ui)->ip_len); 62 if (((struct ip *)ui)->ip_len != len) { 63 if (len > ((struct ip *)ui)->ip_len) { 64 udpstat.udps_badlen++; 65 goto bad; 66 } 67 m_adj(m, ((struct ip *)ui)->ip_len - len); 68 /* (struct ip *)ui->ip_len = len; */ 69 } 70 71 /* 72 * Checksum extended udp header and data. 73 */ 74 if (udpcksum) { 75 ui->ui_next = ui->ui_prev = 0; 76 ui->ui_x1 = 0; 77 ui->ui_len = htons((u_short)(sizeof (struct udphdr) + ulen)); 78 if (ui->ui_sum = in_cksum(m, len)) { 79 udpstat.udps_badsum++; 80 printf("udp cksum %x\n", ui->ui_sum); 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 if (inp == 0) 92 goto bad; 93 94 /* 95 * Construct sockaddr format source address. 96 * Stuff source address and datagram in user buffer. 97 */ 98 udp_in.sin_port = ui->ui_sport; 99 udp_in.sin_addr = ui->ui_src; 100 m->m_len -= sizeof (struct udpiphdr); 101 m->m_off += sizeof (struct udpiphdr); 102 printf("sbappendaddr called with m %x m->m_len %d m->m_off %d\n", 103 m, m->m_len, m->m_off); 104 printf("*mtod(m, char *) %x\n", *mtod(m, char *)); 105 if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, m) == 0) 106 goto bad; 107 sorwakeup(inp->inp_socket); 108 return; 109 bad: 110 m_freem(m); 111 } 112 113 udp_ctlinput(m) 114 struct mbuf *m; 115 { 116 117 COUNT(UDP_CTLINPUT); 118 printf("udp_ctlinput\n"); 119 m_freem(m); 120 } 121 122 /*ARGSUSED*/ 123 udp_output(inp, m0) 124 struct inpcb *inp; 125 struct mbuf *m0; 126 { 127 register struct mbuf *m; 128 register struct udpiphdr *ui; 129 register int len = 0; 130 131 COUNT(UDP_OUTPUT); 132 /* 133 * Calculate data length and get a mbuf 134 * for udp and ip headers. 135 */ 136 for (m = m0; m; m = m->m_next) 137 len += m->m_len; 138 m = m_get(0); 139 if (m == 0) 140 goto bad; 141 142 /* 143 * Fill in mbuf with extended udp header 144 * and addresses and length put into network format. 145 */ 146 m->m_off = MMAXOFF - sizeof (struct udpiphdr); 147 m->m_len = sizeof (struct udpiphdr); 148 m->m_next = m0; 149 ui = mtod(m, struct udpiphdr *); 150 ui->ui_next = ui->ui_prev = 0; 151 ui->ui_x1 = 0; 152 ui->ui_pr = IPPROTO_UDP; 153 ui->ui_len = sizeof (struct udpiphdr) + len; 154 ui->ui_src = inp->inp_laddr; 155 ui->ui_dst = inp->inp_faddr; 156 ui->ui_sport = inp->inp_lport; 157 ui->ui_dport = inp->inp_fport; 158 ui->ui_ulen = htons((u_short)len); 159 160 /* 161 * Stuff checksum and output datagram. 162 */ 163 ui->ui_sum = 0; 164 ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len); 165 ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; 166 ((struct ip *)ui)->ip_ttl = MAXTTL; 167 (void) ip_output(m, (struct mbuf *)0); 168 return; 169 bad: 170 m_freem(m); 171 } 172 173 /*ARGSUSED*/ 174 udp_usrreq(so, req, m, addr) 175 struct socket *so; 176 int req; 177 struct mbuf *m; 178 caddr_t addr; 179 { 180 struct inpcb *inp = sotoinpcb(so); 181 int error; 182 183 COUNT(UDP_USRREQ); 184 if (inp == 0 && req != PRU_ATTACH) 185 return (EINVAL); 186 printf("udp_usrreq %d\n", req); 187 switch (req) { 188 189 case PRU_ATTACH: 190 if (inp != 0) 191 return (EINVAL); 192 error = in_pcbattach(so, &udb, 2048, 2048, (struct sockaddr_in *)addr); 193 if (error) 194 return (error); 195 break; 196 197 case PRU_DETACH: 198 if (inp == 0) 199 return (ENOTCONN); 200 in_pcbdetach(inp); 201 break; 202 203 case PRU_CONNECT: 204 if (inp->inp_faddr.s_addr) 205 return (EISCONN); 206 error = in_pcbconnect(inp, (struct sockaddr_in *)addr); 207 if (error) 208 return (error); 209 soisconnected(so); 210 break; 211 212 case PRU_ACCEPT: 213 return (EOPNOTSUPP); 214 215 case PRU_DISCONNECT: 216 if (inp->inp_faddr.s_addr == 0) 217 return (ENOTCONN); 218 in_pcbdisconnect(inp); 219 soisdisconnected(so); 220 break; 221 222 case PRU_SHUTDOWN: 223 socantsendmore(so); 224 break; 225 226 case PRU_SEND: 227 if (addr) { 228 if (inp->inp_faddr.s_addr) { 229 printf("EISCONN\n"); 230 return (EISCONN); 231 } 232 error = in_pcbconnect(inp, (struct sockaddr_in *)addr); 233 if (error) { 234 printf("pcbconnect error %d\n", error); 235 return (error); 236 } 237 } else { 238 if (inp->inp_faddr.s_addr == 0) 239 return (ENOTCONN); 240 } 241 printf("to udp_output\n"); 242 udp_output(inp, m); 243 if (addr) 244 in_pcbdisconnect(inp); 245 break; 246 247 case PRU_ABORT: 248 in_pcbdetach(inp); 249 sofree(so); 250 soisdisconnected(so); 251 break; 252 253 case PRU_CONTROL: 254 return (EOPNOTSUPP); 255 256 default: 257 panic("udp_usrreq"); 258 } 259 return (0); 260 } 261