source: edk_user_repository/WARP/sw_services/WARPxilnet_v3_00_a/src/xilnet_xilsock.c

Last change on this file was 1749, checked in by chunter, 12 years ago

Updated copyright information and improved handling of broadcast IP address

File size: 14.6 KB
Line 
1////////////////////////////////////////////////////////////////////////////////
2// Copyright (c) 2004 Xilinx, Inc.  All rights reserved.
3//
4// Xilinx, Inc.
5// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
6// COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
7// ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
8// STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
9// IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
10// FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
11// XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
12// THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
13// ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
14// FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
15// AND FITNESS FOR A PARTICULAR PURPOSE.
16//
17// File   : xilsock.c
18// Date   : 2002, March 20.
19// Author : Sathya Thammanur
20// Company: Xilinx
21// Group  : Emerging Software Technologies
22//
23// Summary:
24// Xilinx internal socket related functions (xilsock functions)
25//
26// $Id: xilsock.c,v 1.2.8.6 2005/11/15 23:41:10 salindac Exp $
27//
28////////////////////////////////////////////////////////////////////////////////
29
30////////////////////////////////////////////////////////////////////////////////
31// see copyright.txt for Rice University/Mango Communications modifications
32////////////////////////////////////////////////////////////////////////////////
33
34#include <xilnet_xilsock.h>
35
36/* buffers for sending and receiving packets */
37unsigned char recvbuf[LINK_FRAME_LEN];
38unsigned char sendbuf[LINK_FRAME_LEN];
39unsigned char mb_ip_addr[IP_VERSION] = {0,0,0,0};    /* microblaze ip address , currently set to 127.0.0.0 */
40unsigned char mb_hw_addr[ETH_ADDR_LEN] = {0x00,0x60,0x08,0x11,0x27,0x7b};  /* microblaze hardware address */
41
42unsigned char sync_IP_octet = 255;
43
44struct xilsock_socket xilsock_sockets[NO_OF_XILSOCKS];
45/* gives the status of the received packet */
46int xilsock_status_flag = 0;
47
48/*
49 * Initialisation of xilsock_sockets
50 */
51
52unsigned char is_xilsock_init = 0;
53
54int xilsock_init (void) {
55
56   int i;
57   if (!is_xilsock_init) {
58      for (i = 0; i < NO_OF_XILSOCKS; i++) {
59         xilsock_sockets[i].type = 0;
60         xilsock_sockets[i].domain = 0;
61         xilsock_sockets[i].proto = 0;
62         xilsock_sockets[i].listen = 0;
63         xilsock_sockets[i].bound = 0;
64         xilsock_sockets[i].accept = 0;
65         xilsock_sockets[i].connect = 0;
66         xilsock_sockets[i].closing = 0;
67         xilsock_sockets[i].closed = 0;
68         xilsock_sockets[i].free = 1;
69         xilsock_sockets[i].conn.tcp_conn = NULL;
70         xilsock_sockets[i].recvbuf.buf = NULL;
71         xilsock_sockets[i].recvbuf.size = 0;
72      }
73      is_xilsock_init = 1;
74   }
75   return is_xilsock_init;
76}
77
78
79/*
80 * Release a socket
81 */
82
83void xilsock_rel_socket (int sd) {
84
85   if (xilsock_sockets[sd].type == SOCK_STREAM) {
86      xilsock_sockets[sd].conn.tcp_conn = NULL;
87   }
88   else {
89      xilsock_sockets[sd].conn.udp_conn = NULL;
90   }
91   xilsock_sockets[sd].type = 0;
92   xilsock_sockets[sd].domain = 0;
93   xilsock_sockets[sd].proto = 0;
94   xilsock_sockets[sd].listen = 0;
95   xilsock_sockets[sd].bound = 0;
96   xilsock_sockets[sd].accept = 0;
97   xilsock_sockets[sd].connect = 0;
98   xilsock_sockets[sd].closing = 0;
99   xilsock_sockets[sd].closed = 0;
100   xilsock_sockets[sd].free = 1;
101   xilsock_sockets[sd].recvbuf.buf = NULL;
102   xilsock_sockets[sd].recvbuf.size = 0;
103
104}
105
106
107/*
108 * Allocate a xilsock_socket and return socket descriptor
109 * if not able to alloc socket, return -1
110 */
111
112int xilsock_socket(int domain, int type, int proto) {
113
114   int sd;
115
116   // find a free xilsock_socket
117   if (!xilsock_init())
118      return (-1);
119   for (sd = 0; sd < NO_OF_XILSOCKS; sd++) {
120      if (xilsock_sockets[sd].free) {
121         // initialise the socket & make it unavailable
122         xilsock_sockets[sd].domain = domain;
123         xilsock_sockets[sd].type = type;
124         xilsock_sockets[sd].proto = proto;
125         xilsock_sockets[sd].free = 0;
126         return sd;
127      }
128   }
129   // return as no sockets available
130   return -1;
131}
132
133
134/*
135 * bind a socket to the specified address.
136 * binds addr to socket sd. returns 1 if bound
137 * returns -1 if not able to bind
138 */
139
140int xilsock_bind(int sd, struct sockaddr* addr, int addrlen) {
141
142   int connd;
143
144   // open a tcp conn/udp conn
145   if (xilsock_sockets[sd].type == SOCK_STREAM) {
146      if ( (connd = xilnet_tcp_open_conn (((struct sockaddr_in*)addr)->sin_port)) == -1) {
147         print("bind: tcp sockets not available \n");
148         xilsock_rel_socket(sd);
149         return -1;
150      }
151      xilsock_sockets[sd].conn.tcp_conn = (xilnet_tcp_conns + connd);
152      // update fd of tcp conn
153      xilnet_tcp_conns[connd].fd = sd;
154   }
155   else if (xilsock_sockets[sd].type == SOCK_DGRAM) {
156      if ( (connd = xilnet_udp_open_conn (((struct sockaddr_in*)addr)->sin_port)) == -1) {
157         print("bind: udp sockets not available \n");
158         xilsock_rel_socket(sd);
159         return -1;
160      }
161      xilsock_sockets[sd].conn.udp_conn = (xilnet_udp_conns + connd);
162      // update fd of udp conn
163      xilnet_udp_conns[connd].fd = sd;
164   }
165
166   return 1;
167}
168
169
170/*
171 * listen on a socket
172 * called from listen()
173 */
174
175int xilsock_listen(int s, int backlog) {
176
177   xilsock_sockets[s].listen = 1;
178   return 1;
179
180}
181
182
183/*
184 * accept a conn on the socket
185 * if pkt for new conn, open new xilsock_socket, return 0
186 * if pkt for exisiting conn, return 0
187 */
188
189int xilsock_accept(int sd, struct sockaddr* addr, int *addrlen) {
190
191   int n = 0;
192   int nsd;
193   int ns;
194   struct xilnet_tcp_conn* new_conn;
195   struct xilnet_tcp_conn* curr_conn;
196   int connd;
197   unsigned char *buf = recvbuf; // recvbuf is the array to recv messages
198   int len = LINK_FRAME_LEN;
199
200   // reset status flag
201   xilsock_status_flag = 0;
202
203   // check for tcp conn to execute this call
204   if (xilsock_sockets[sd].type != SOCK_STREAM) {
205      print("accept: not a tcp socket \n");
206      return -1;
207   }
208
209   // call eth recv. if return val is 1, new conn
210   // create new file, socket with same properties
211   // else no new conn., return -1
212
213   n = xilnet_eth_recv_frame(buf, len);
214   if (n < 0) // not for any of the supported conns
215      return -1;
216
217   if ( n == XILSOCK_NEW_CONN) {
218      // create a new socket
219      nsd = xilsock_socket(xilsock_sockets[sd].domain, xilsock_sockets[sd].type, xilsock_sockets[sd].proto);
220      if (nsd < 0) {
221         print("xilsock sockets not available \n");
222         return (-1);
223      }
224      if ( (connd = xilnet_tcp_open_conn (xilsock_sockets[sd].conn.tcp_conn->src_port)) == -1) {
225         print("accept: tcp sockets not available \n");
226         xilsock_rel_socket(nsd);
227         return -1;
228      }
229      // copy the orig socket characteristics to new socket
230      xilsock_sockets[nsd].type = xilsock_sockets[sd].type;
231      xilsock_sockets[nsd].domain = xilsock_sockets[sd].domain;
232      xilsock_sockets[nsd].proto = xilsock_sockets[sd].proto;
233      xilsock_sockets[nsd].connect = 1;
234      new_conn = xilsock_sockets[nsd].conn.tcp_conn = (xilnet_tcp_conns + connd);
235      curr_conn = xilsock_sockets[sd].conn.tcp_conn;
236
237      // update new tcp conn which starts listening
238      new_conn->fd = nsd;
239      new_conn->dst_ip[0] = xilsock_sockets[sd].conn.tcp_conn->dst_ip[0];
240      new_conn->dst_ip[1] = xilsock_sockets[sd].conn.tcp_conn->dst_ip[1];
241      new_conn->dst_ip[2] = xilsock_sockets[sd].conn.tcp_conn->dst_ip[2];
242      new_conn->dst_ip[3] = xilsock_sockets[sd].conn.tcp_conn->dst_ip[3];
243      new_conn->dst_port = xilsock_sockets[sd].conn.tcp_conn->dst_port;
244      new_conn->seqno = curr_conn->seqno;
245      new_conn->ack_seqno = curr_conn->ack_seqno;
246      new_conn->exp_acknum = curr_conn->exp_acknum;
247      new_conn->state = curr_conn->state;
248
249      // reset the listening connection
250      curr_conn->state = TCP_LISTEN;
251      curr_conn->dst_ip[0] = 0;
252      curr_conn->dst_ip[1] = 0;
253      curr_conn->dst_ip[2] = 0;
254      curr_conn->dst_ip[3] = 0;
255      curr_conn->dst_port = 0;
256      curr_conn->seqno = 0;
257      curr_conn->ack_seqno = 0;
258      curr_conn->exp_acknum = 0;
259      xilsock_sockets[sd].listen = 1;
260
261      // send a reply using new socket
262      memset(sendbuf, 0, LINK_FRAME_LEN);
263      xilnet_tcp_send_pkt(new_conn, (sendbuf + LINK_HDR_LEN + (IP_HDR_LEN*4)), 0, (TCP_SYN|TCP_ACK));
264      xilnet_ip_header(sendbuf+LINK_HDR_LEN,(IP_HDR_LEN*4)+(TCP_HDR_LEN*4), IP_PROTO_TCP, new_conn->dst_ip);
265      xilnet_eth_send_frame(sendbuf,LINK_HDR_LEN+(IP_HDR_LEN*4)+(TCP_HDR_LEN*4), new_conn->dst_ip, 0, ETH_PROTO_IP);
266      new_conn->exp_acknum += 1;
267
268      // set status flag
269      xilsock_status_flag |= XILSOCK_NEW_CONN;
270      return nsd;
271   }
272   else if (n == XILSOCK_CLOSE_CONN) {
273      int i;
274      for ( i = 0; i < NO_OF_XILSOCKS; i++) {
275         if (xilsock_sockets[i].closed) {
276            // close conn
277            if (xilsock_sockets[i].type == SOCK_STREAM)
278               xilnet_tcp_close_conn(xilsock_sockets[i].conn.tcp_conn);
279            else if (xilsock_sockets[i].type == SOCK_DGRAM)
280               xilnet_udp_close_conn(xilsock_sockets[i].conn.udp_conn);
281            // close the socket
282            xilsock_rel_socket(i);
283        // set status flag
284            xilsock_status_flag |= XILSOCK_CLOSE_CONN;
285            return -1;
286         }
287      }
288   }
289   // set status flag
290   xilsock_status_flag |= n;
291   return n;
292}
293
294
295/*
296 * recv data on socket
297 * called from recv()
298 * returns -1 if no data recvd for "s" (non_blocking call) or
299 * number of bytes recvd for "s"
300 */
301
302int xilsock_recv(int s, unsigned char *buf, unsigned int len) {
303
304   int n;
305   int i;
306   int bytes_recvd = 0;
307
308   if (s > NO_OF_XILSOCKS) {
309      print("recv: invalid socket descriptor \n");
310      return -1;
311   }
312
313   n = xilnet_eth_recv_frame(buf, len);
314
315   // Return if data not for socket s
316   if ((n < 0 ) || (xilsock_sockets[s].recvbuf.buf == NULL))
317      return -1;
318
319   // Copy data if required onto buf
320   if (xilsock_sockets[s].recvbuf.buf != buf)
321   {
322      memcpy(buf, xilsock_sockets[s].recvbuf.buf, len);
323      bytes_recvd = xilsock_sockets[s].recvbuf.size;
324
325      //reset socket buffer and size
326      xilsock_sockets[s].recvbuf.buf = NULL;
327      xilsock_sockets[s].recvbuf.size = 0;
328   }
329
330
331   // return no of bytes recvd for this conn
332   //return xilsock_sockets[s].recvbuf.size;
333   return bytes_recvd;
334
335}
336
337
338/*
339 * send data on socket
340 * called from send()
341 */
342
343int xilsock_send(int s,  unsigned char* buf, unsigned int len) {
344
345   struct xilnet_tcp_conn *conn;
346
347   conn = xilsock_sockets[s].conn.tcp_conn;
348
349   if (!conn) {
350      print("send: no such socket \n");
351      return -1;
352   }
353
354   if (buf != sendbuf) {
355      memset(sendbuf, 0, LINK_FRAME_LEN);
356      memcpy(sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4+(TCP_HDR_LEN*4), buf, len);
357   }
358
359   xilnet_tcp_send_pkt(conn, sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4, len, TCP_ACK);
360   xilnet_ip_header(sendbuf+LINK_HDR_LEN, len+(TCP_HDR_LEN*4)+IP_HDR_LEN*4, IP_PROTO_TCP, conn->dst_ip);
361
362   xilnet_eth_send_frame(sendbuf, len+(TCP_HDR_LEN*4)+IP_HDR_LEN*4+ETH_HDR_LEN, conn->dst_ip, NULL, ETH_PROTO_IP);
363
364   return len;
365
366}
367
368
369/*
370 * recvfrom socket
371 * Data recvd on any UDP socket
372 * return -1 if data not for socket "s" [non-blocking call]
373 */
374int xilsock_recvfrom(int s, unsigned char *buf, unsigned int len,
375                     struct sockaddr* from, unsigned int *fromlen)
376{
377   int n;
378   int i;
379   int bytes_recvd = 0;
380
381   struct xilnet_udp_conn *conn = xilsock_sockets[s].conn.udp_conn;
382
383   if (s > NO_OF_XILSOCKS) {
384      print("recvfrom: invalid socket descriptor \n");
385      return -1;
386   }
387
388   n = xilnet_eth_recv_frame(buf, len);
389
390   // Return if data not for socket s
391   if ((n < 0 ) || (xilsock_sockets[s].recvbuf.buf == NULL))
392      return -1;
393
394   // Copy data if required onto buf
395   if (xilsock_sockets[s].recvbuf.buf != buf)
396   {
397      memcpy(buf, xilsock_sockets[s].recvbuf.buf, len);
398      bytes_recvd = xilsock_sockets[s].recvbuf.size;
399
400      //reset socket buffer and size
401      xilsock_sockets[s].recvbuf.buf = NULL;
402      xilsock_sockets[s].recvbuf.size = 0;
403   }
404
405   // Copy the source address onto "to"
406   ((struct sockaddr_in*)from)->sin_addr.s_addr =
407      (conn->dst_ip[0] << 24) + (conn->dst_ip[1] << 16) + (conn->dst_ip[2] << 8) + conn->dst_ip[3];
408   ((struct sockaddr_in*)from)->sin_port = conn->dst_port;
409   *fromlen = sizeof(from);
410
411   // return no of bytes recvd for this conn
412   return bytes_recvd;
413
414}
415
416
417/*
418 * sendto socket
419 * called from sendto()
420 */
421
422int xilsock_sendto(int s,  unsigned char* buf, unsigned int len, struct sockaddr* to, unsigned int tolen)
423{
424
425   struct xilnet_udp_conn *conn;
426   unsigned int dstaddr = ((struct sockaddr_in*)to)->sin_addr.s_addr;
427
428   conn = xilsock_sockets[s].conn.udp_conn;
429   conn->dst_ip[0] = (unsigned char) ((dstaddr >> 24) & 0xFF);
430   conn->dst_ip[1] = (unsigned char) ((dstaddr >> 16) & 0xFF);
431   conn->dst_ip[2] = (unsigned char) ((dstaddr >> 8) & 0xFF);
432   conn->dst_ip[3] = (unsigned char) ((dstaddr) & 0xFF);
433   conn->dst_port = ((struct sockaddr_in*)to)->sin_port;
434
435   if (!conn) {
436      print("sendto: no such socket \n");
437      return -1;
438   }
439
440   if (buf != sendbuf) {
441      memset(sendbuf, 0, LINK_FRAME_LEN);
442      memcpy(sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4+UDP_HDR_LEN, buf, len);
443   }
444
445   // calls to udp stack
446   xilnet_udp_header(conn, sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4, len+UDP_HDR_LEN);
447   xilnet_ip_header(sendbuf+LINK_HDR_LEN, len+UDP_HDR_LEN+IP_HDR_LEN*4, IP_PROTO_UDP, conn->dst_ip);
448
449   xilnet_eth_send_frame(sendbuf, len+UDP_HDR_LEN+IP_HDR_LEN*4+ETH_HDR_LEN, conn->dst_ip, NULL, ETH_PROTO_IP);
450
451   return len;
452}
453
454
455/*
456 * close socket
457 */
458
459void xilsock_close(int s) {
460
461   unsigned char flags = 0;
462   unsigned short check = 0;
463   unsigned char *tcp_reply;
464
465   if (xilsock_sockets[s].type == SOCK_STREAM) {
466      struct xilnet_tcp_conn *conn = xilsock_sockets[s].conn.tcp_conn;
467
468      // construct the FIN and wait for ack & FIN from client
469      flags = (TCP_FIN | TCP_ACK);
470      ((struct xilnet_tcp_conn*)conn)->state = TCP_FIN_WAIT1;
471      memset(sendbuf, 0, LINK_FRAME_LEN);
472      tcp_reply = sendbuf+ETH_HDR_LEN+(IP_HDR_LEN*4);
473
474      xilnet_tcp_header(((struct xilnet_tcp_conn*)conn), tcp_reply, 1, flags);
475
476      // calculate tcp checksum
477      check = xilnet_udp_tcp_calc_chksum(tcp_reply, (TCP_HDR_LEN*4), mb_ip_addr, ((struct xilnet_tcp_conn*)conn)->dst_ip, IP_PROTO_TCP);
478      tcp_reply[TCP_CHECK_OFF] = (check & 0xff00) >> 8;
479      tcp_reply[TCP_CHECK_OFF+1] = (check & 0x00ff);
480
481      xilnet_ip_header(sendbuf+ETH_HDR_LEN,(IP_HDR_LEN*4)+(TCP_HDR_LEN*4), IP_PROTO_TCP, ((struct xilnet_tcp_conn*)conn)->dst_ip);
482      xilnet_eth_send_frame(sendbuf, (TCP_HDR_LEN*4)+(IP_HDR_LEN*4)+ETH_HDR_LEN, ((struct xilnet_tcp_conn*)conn)->dst_ip, NULL, ETH_PROTO_IP);
483
484
485   }
486   else if (xilsock_sockets[s].type == SOCK_DGRAM) {
487      xilnet_udp_close_conn(xilsock_sockets[s].conn.udp_conn);
488      // close the socket
489      xilsock_rel_socket(s);
490   }
491
492}
Note: See TracBrowser for help on using the repository browser.