ip_client.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2009 Lukas Mejdrech
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00038 #include <errno.h>
00039 #include <sys/types.h>
00040 
00041 #include <ip_client.h>
00042 #include <packet_client.h>
00043 #include <ip_header.h>
00044 
00045 #include <net/packet.h>
00046 
00053 size_t ip_client_header_length(packet_t *packet)
00054 {
00055         ip_header_t *header;
00056 
00057         header = (ip_header_t *) packet_get_data(packet);
00058         if (!header || (packet_get_data_length(packet) < sizeof(ip_header_t)))
00059                 return 0;
00060 
00061         return IP_HEADER_LENGTH(header);
00062 }
00063 
00088 int
00089 ip_client_get_pseudo_header(ip_protocol_t protocol, struct sockaddr *src,
00090     socklen_t srclen, struct sockaddr *dest, socklen_t destlen,
00091     size_t data_length, void **header, size_t *headerlen)
00092 {
00093         ipv4_pseudo_header_t *header_in;
00094         struct sockaddr_in *address_in;
00095 
00096         if (!header || !headerlen)
00097                 return EBADMEM;
00098 
00099         if (!src || !dest || srclen <= 0 ||
00100             (((size_t) srclen < sizeof(struct sockaddr))) ||
00101             (srclen != destlen) || (src->sa_family != dest->sa_family)) {
00102                 return EINVAL;
00103         }
00104 
00105         switch (src->sa_family) {
00106         case AF_INET:
00107                 if (srclen != sizeof(struct sockaddr_in))
00108                         return EINVAL;
00109                 
00110                 *headerlen = sizeof(*header_in);
00111                 header_in = (ipv4_pseudo_header_t *) malloc(*headerlen);
00112                 if (!header_in)
00113                         return ENOMEM;
00114 
00115                 bzero(header_in, *headerlen);
00116                 address_in = (struct sockaddr_in *) dest;
00117                 header_in->destination_address = address_in->sin_addr.s_addr;
00118                 address_in = (struct sockaddr_in *) src;
00119                 header_in->source_address = address_in->sin_addr.s_addr;
00120                 header_in->protocol = protocol;
00121                 header_in->data_length = htons(data_length);
00122                 *header = header_in;
00123                 return EOK;
00124 
00125         // TODO IPv6
00126 #if 0
00127         case AF_INET6:
00128                 if (addrlen != sizeof(struct sockaddr_in6))
00129                         return EINVAL;
00130 
00131                 address_in6 = (struct sockaddr_in6 *) addr;
00132                 return EOK;
00133 #endif
00134 
00135         default:
00136                 return EAFNOSUPPORT;
00137         }
00138 }
00139 
00154 int
00155 ip_client_prepare_packet(packet_t *packet, ip_protocol_t protocol, ip_ttl_t ttl,
00156     ip_tos_t tos, int dont_fragment, size_t ipopt_length)
00157 {
00158         ip_header_t *header;
00159         uint8_t *data;
00160         size_t padding;
00161 
00162         /*
00163          * Compute the padding if IP options are set
00164          * multiple of 4 bytes
00165          */
00166         padding =  ipopt_length % 4;
00167         if (padding) {
00168                 padding = 4 - padding;
00169                 ipopt_length += padding;
00170         }
00171 
00172         /* Prefix the header */
00173         data = (uint8_t *) packet_prefix(packet, sizeof(ip_header_t) + padding);
00174         if (!data)
00175                 return ENOMEM;
00176 
00177         /* Add the padding */
00178         while (padding--)
00179                 data[sizeof(ip_header_t) + padding] = IPOPT_NOOP;
00180 
00181         /* Set the header */
00182         header = (ip_header_t *) data;
00183         SET_IP_HEADER_LENGTH(header,
00184             (IP_COMPUTE_HEADER_LENGTH(sizeof(ip_header_t) + ipopt_length)));
00185         header->ttl = (ttl ? ttl : IPDEFTTL);
00186         header->tos = tos;
00187         header->protocol = protocol;
00188 
00189         if (dont_fragment)
00190                 SET_IP_HEADER_FLAGS(header, IPFLAG_DONT_FRAGMENT);
00191 
00192         return EOK;
00193 }
00194 
00212 int
00213 ip_client_process_packet(packet_t *packet, ip_protocol_t *protocol,
00214     ip_ttl_t *ttl, ip_tos_t *tos, int *dont_fragment, size_t *ipopt_length)
00215 {
00216         ip_header_t *header;
00217 
00218         header = (ip_header_t *) packet_get_data(packet);
00219         if (!header || (packet_get_data_length(packet) < sizeof(ip_header_t)))
00220                 return ENOMEM;
00221 
00222         if (protocol)
00223                 *protocol = header->protocol;
00224         if (ttl)
00225                 *ttl = header->ttl;
00226         if (tos)
00227                 *tos = header->tos;
00228         if (dont_fragment)
00229                 *dont_fragment = GET_IP_HEADER_FLAGS(header) & IPFLAG_DONT_FRAGMENT;
00230         if (ipopt_length) {
00231                 *ipopt_length = IP_HEADER_LENGTH(header) - sizeof(ip_header_t);
00232                 return sizeof(ip_header_t);
00233         } else {
00234                 return IP_HEADER_LENGTH(header);
00235         }
00236 }
00237 
00248 int
00249 ip_client_set_pseudo_header_data_length(void *header, size_t headerlen,
00250     size_t data_length)
00251 {
00252         ipv4_pseudo_header_t *header_in;
00253 
00254         if (!header)
00255                 return EBADMEM;
00256 
00257         if (headerlen == sizeof(ipv4_pseudo_header_t)) {
00258                 header_in = (ipv4_pseudo_header_t *) header;
00259                 header_in->data_length = htons(data_length);
00260                 return EOK;
00261         // TODO IPv6
00262         } else {
00263                 return EINVAL;
00264         }
00265 }
00266 

Generated on Thu Jun 2 07:45:48 2011 for HelenOS/USB by  doxygen 1.4.7