• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
core_udp_open(struct pxe_pvt_inode * socket)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  */
core_udp_close(struct pxe_pvt_inode * socket)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  */
core_udp_connect(struct pxe_pvt_inode * socket,uint32_t ip,uint16_t port)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  */
core_udp_disconnect(struct pxe_pvt_inode * socket)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  */
core_udp_recv(struct pxe_pvt_inode * socket,void * buf,uint16_t * buf_len,uint32_t * src_ip,uint16_t * src_port)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  */
core_udp_send(struct pxe_pvt_inode * socket,const void * data,size_t len)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  */
core_udp_sendto(struct pxe_pvt_inode * socket,const void * data,size_t len,uint32_t ip,uint16_t port)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  */
net_core_init(void)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 
probe_undi(void)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 
core_tcp_open(struct pxe_pvt_inode * socket)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 }
core_tcp_connect(struct pxe_pvt_inode * socket,uint32_t ip,uint16_t port)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 
core_tcp_write(struct pxe_pvt_inode * socket,const void * data,size_t len,bool copy)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 
core_tcp_close_file(struct inode * inode)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 
core_tcp_is_connected(struct pxe_pvt_inode * socket)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 
core_tcp_fill_buffer(struct inode * inode)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