1 #include <syslinux/pxe_api.h> 2 #include <lwip/api.h> 3 #include <lwip/tcpip.h> 4 #include <lwip/dns.h> 5 #include <core.h> 6 #include <net.h> 7 #include "pxe.h" 8 9 #include <dprintf.h> 10 11 const struct url_scheme url_schemes[] = { 12 { "tftp", tftp_open, 0 }, 13 { "http", http_open, O_DIRECTORY }, 14 { "ftp", ftp_open, O_DIRECTORY }, 15 { NULL, NULL, 0 }, 16 }; 17 18 /** 19 * Open a socket 20 * 21 * @param:socket, the socket to open 22 * 23 * @out: error code, 0 on success, -1 on failure 24 */ 25 int core_udp_open(struct pxe_pvt_inode *socket) 26 { 27 struct net_private_lwip *priv = &socket->net.lwip; 28 int err; 29 30 priv->conn = netconn_new(NETCONN_UDP); 31 if (!priv->conn) 32 return -1; 33 34 priv->conn->recv_timeout = 15; /* A 15 ms recv timeout... */ 35 err = netconn_bind(priv->conn, NULL, 0); 36 if (err) { 37 ddprintf("netconn_bind error %d\n", err); 38 return -1; 39 } 40 41 return 0; 42 } 43 44 /** 45 * Close a socket 46 * 47 * @param:socket, the socket to open 48 */ 49 void core_udp_close(struct pxe_pvt_inode *socket) 50 { 51 struct net_private_lwip *priv = &socket->net.lwip; 52 53 if (priv->conn) { 54 netconn_delete(priv->conn); 55 priv->conn = NULL; 56 } 57 } 58 59 /** 60 * Establish a connection on an open socket 61 * 62 * @param:socket, the open socket 63 * @param:ip, the ip address 64 * @param:port, the port number, host-byte order 65 */ 66 void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t ip, 67 uint16_t port) 68 { 69 struct net_private_lwip *priv = &socket->net.lwip; 70 struct ip_addr addr; 71 72 dprintf("net_core_connect: %08X %04X\n", ntohl(ip), port); 73 addr.addr = ip; 74 netconn_connect(priv->conn, &addr, port); 75 } 76 77 /** 78 * Tear down a connection on an open socket 79 * 80 * @param:socket, the open socket 81 */ 82 void core_udp_disconnect(struct pxe_pvt_inode *socket) 83 { 84 struct net_private_lwip *priv = &socket->net.lwip; 85 netconn_disconnect(priv->conn); 86 } 87 88 /** 89 * Read data from the network stack 90 * 91 * @param:socket, the open socket 92 * @param:buf, location of buffer to store data 93 * @param:buf_len, size of buffer 94 95 * @out: src_ip, ip address of the data source 96 * @out: src_port, port number of the data source, host-byte order 97 */ 98 int core_udp_recv(struct pxe_pvt_inode *socket, void *buf, uint16_t *buf_len, 99 uint32_t *src_ip, uint16_t *src_port) 100 { 101 struct net_private_lwip *priv = &socket->net.lwip; 102 struct netbuf *nbuf; 103 u16_t nbuf_len; 104 int err; 105 106 err = netconn_recv(priv->conn, &nbuf); 107 if (err) 108 return err; 109 110 if (!nbuf) 111 return -1; 112 113 *src_ip = netbuf_fromaddr(nbuf)->addr; 114 *src_port = netbuf_fromport(nbuf); 115 116 netbuf_first(nbuf); /* XXX needed? */ 117 nbuf_len = netbuf_len(nbuf); 118 if (nbuf_len <= *buf_len) 119 netbuf_copy(nbuf, buf, nbuf_len); 120 else 121 nbuf_len = 0; /* impossible mtu < PKTBUF_SIZE */ 122 netbuf_delete(nbuf); 123 124 *buf_len = nbuf_len; 125 return 0; 126 } 127 128 /** 129 * Send a UDP packet. 130 * 131 * @param:socket, the open socket 132 * @param:data, data buffer to send 133 * @param:len, size of data bufer 134 */ 135 void core_udp_send(struct pxe_pvt_inode *socket, const void *data, size_t len) 136 { 137 struct netconn *conn = socket->net.lwip.conn; 138 struct netbuf *nbuf; 139 void *pbuf; 140 int err; 141 142 nbuf = netbuf_new(); 143 if (!nbuf) { 144 ddprintf("netbuf allocation error\n"); 145 return; 146 } 147 148 pbuf = netbuf_alloc(nbuf, len); 149 if (!pbuf) { 150 ddprintf("pbuf allocation error\n"); 151 goto out; 152 } 153 154 memcpy(pbuf, data, len); 155 156 err = netconn_send(conn, nbuf); 157 if (err) { 158 ddprintf("netconn_send error %d\n", err); 159 goto out; 160 } 161 162 out: 163 netbuf_delete(nbuf); 164 } 165 166 /** 167 * Send a UDP packet to a destination 168 * 169 * @param:socket, the open socket 170 * @param:data, data buffer to send 171 * @param:len, size of data bufer 172 * @param:ip, the ip address 173 * @param:port, the port number, host-byte order 174 */ 175 void core_udp_sendto(struct pxe_pvt_inode *socket, const void *data, 176 size_t len, uint32_t ip, uint16_t port) 177 { 178 struct netconn *conn = socket->net.lwip.conn; 179 struct ip_addr addr; 180 struct netbuf *nbuf; 181 void *pbuf; 182 int err; 183 184 nbuf = netbuf_new(); 185 if (!nbuf) { 186 ddprintf("netbuf allocation error\n"); 187 return; 188 } 189 190 pbuf = netbuf_alloc(nbuf, len); 191 if (!pbuf) { 192 ddprintf("pbuf allocation error\n"); 193 goto out; 194 } 195 196 memcpy(pbuf, data, len); 197 198 dprintf("core_udp_sendto: %08X %04X\n", ntohl(ip), port); 199 addr.addr = ip; 200 201 err = netconn_sendto(conn, nbuf, &addr, port); 202 if (err) { 203 ddprintf("netconn_sendto error %d\n", err); 204 goto out; 205 } 206 207 out: 208 netbuf_delete(nbuf); 209 } 210 211 /** 212 * Network stack-specific initialization 213 */ 214 void net_core_init(void) 215 { 216 int err; 217 int i; 218 219 http_bake_cookies(); 220 221 /* Initialize lwip */ 222 tcpip_init(NULL, NULL); 223 224 /* Start up the undi driver for lwip */ 225 err = undiif_start(IPInfo.myip, IPInfo.netmask, IPInfo.gateway); 226 if (err) { 227 ddprintf("undiif driver failed to start: %d\n", err); 228 kaboom(); 229 } 230 231 for (i = 0; i < DNS_MAX_SERVERS; i++) { 232 /* Transfer the DNS information to lwip */ 233 dns_setserver(i, (struct ip_addr *)&dns_server[i]); 234 } 235 } 236 237 void probe_undi(void) 238 { 239 /* Probe UNDI information */ 240 pxe_call(PXENV_UNDI_GET_INFORMATION, &pxe_undi_info); 241 pxe_call(PXENV_UNDI_GET_IFACE_INFO, &pxe_undi_iface); 242 243 ddprintf("UNDI: baseio %04x int %d MTU %d type %d \"%s\" flags 0x%x\n", 244 pxe_undi_info.BaseIo, pxe_undi_info.IntNumber, 245 pxe_undi_info.MaxTranUnit, pxe_undi_info.HwType, 246 pxe_undi_iface.IfaceType, pxe_undi_iface.ServiceFlags); 247 } 248 249 int core_tcp_open(struct pxe_pvt_inode *socket) 250 { 251 socket->net.lwip.conn = netconn_new(NETCONN_TCP); 252 if (!socket->net.lwip.conn) 253 return -1; 254 255 return 0; 256 } 257 int core_tcp_connect(struct pxe_pvt_inode *socket, uint32_t ip, uint16_t port) 258 { 259 struct ip_addr addr; 260 err_t err; 261 262 addr.addr = ip; 263 err = netconn_connect(socket->net.lwip.conn, &addr, port); 264 if (err) { 265 printf("netconn_connect error %d\n", err); 266 return -1; 267 } 268 269 return 0; 270 } 271 272 int core_tcp_write(struct pxe_pvt_inode *socket, const void *data, size_t len, 273 bool copy) 274 { 275 err_t err; 276 u8_t flags = copy ? NETCONN_COPY : NETCONN_NOCOPY; 277 278 err = netconn_write(socket->net.lwip.conn, data, len, flags); 279 if (err) { 280 printf("netconn_write failed: %d\n", err); 281 return -1; 282 } 283 284 return 0; 285 } 286 287 void core_tcp_close_file(struct inode *inode) 288 { 289 struct pxe_pvt_inode *socket = PVT(inode); 290 291 if (socket->net.lwip.conn) { 292 netconn_delete(socket->net.lwip.conn); 293 socket->net.lwip.conn = NULL; 294 } 295 if (socket->net.lwip.buf) { 296 netbuf_delete(socket->net.lwip.buf); 297 socket->net.lwip.buf = NULL; 298 } 299 } 300 301 bool core_tcp_is_connected(struct pxe_pvt_inode *socket) 302 { 303 if (socket->net.lwip.conn) 304 return true; 305 306 return false; 307 } 308 309 void core_tcp_fill_buffer(struct inode *inode) 310 { 311 struct pxe_pvt_inode *socket = PVT(inode); 312 void *data; 313 u16_t len; 314 err_t err; 315 316 /* Clean up or advance an inuse netbuf */ 317 if (socket->net.lwip.buf) { 318 if (netbuf_next(socket->net.lwip.buf) < 0) { 319 netbuf_delete(socket->net.lwip.buf); 320 socket->net.lwip.buf = NULL; 321 } 322 } 323 /* If needed get a new netbuf */ 324 if (!socket->net.lwip.buf) { 325 err = netconn_recv(socket->net.lwip.conn, &(socket->net.lwip.buf)); 326 if (!socket->net.lwip.buf || err) { 327 socket->tftp_goteof = 1; 328 if (inode->size == -1) 329 inode->size = socket->tftp_filepos; 330 socket->ops->close(inode); 331 return; 332 } 333 } 334 /* Report the current fragment of the netbuf */ 335 err = netbuf_data(socket->net.lwip.buf, &data, &len); 336 if (err) { 337 printf("netbuf_data err: %d\n", err); 338 kaboom(); 339 } 340 socket->tftp_dataptr = data; 341 socket->tftp_filepos += len; 342 socket->tftp_bytesleft = len; 343 return; 344 } 345