Home | History | Annotate | Download | only in pxe
      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