tl_common.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008 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 <tl_common.h>
00039 #include <packet_client.h>
00040 #include <packet_remote.h>
00041 #include <icmp_remote.h>
00042 #include <ip_remote.h>
00043 #include <ip_interface.h>
00044 #include <tl_remote.h>
00045 
00046 #include <net/socket_codes.h>
00047 #include <net/in.h>
00048 #include <net/in6.h>
00049 #include <net/inet.h>
00050 #include <net/device.h>
00051 #include <net/packet.h>
00052 
00053 #include <async.h>
00054 #include <ipc/services.h>
00055 #include <errno.h>
00056 
00057 DEVICE_MAP_IMPLEMENT(packet_dimensions, packet_dimension_t);
00058 
00071 int
00072 tl_get_address_port(const struct sockaddr *addr, int addrlen, uint16_t *port)
00073 {
00074         const struct sockaddr_in *address_in;
00075         const struct sockaddr_in6 *address_in6;
00076 
00077         if ((addrlen <= 0) || ((size_t) addrlen < sizeof(struct sockaddr)))
00078                 return EINVAL;
00079 
00080         switch (addr->sa_family) {
00081         case AF_INET:
00082                 if (addrlen != sizeof(struct sockaddr_in))
00083                         return EINVAL;
00084 
00085                 address_in = (struct sockaddr_in *) addr;
00086                 *port = ntohs(address_in->sin_port);
00087                 break;
00088         
00089         case AF_INET6:
00090                 if (addrlen != sizeof(struct sockaddr_in6))
00091                         return EINVAL;
00092 
00093                 address_in6 = (struct sockaddr_in6 *) addr;
00094                 *port = ntohs(address_in6->sin6_port);
00095                 break;
00096         
00097         default:
00098                 return EAFNOSUPPORT;
00099         }
00100 
00101         return EOK;
00102 }
00103 
00120 int
00121 tl_get_ip_packet_dimension(int ip_phone,
00122     packet_dimensions_t *packet_dimensions, device_id_t device_id,
00123     packet_dimension_t **packet_dimension)
00124 {
00125         int rc;
00126         
00127         if (!packet_dimension)
00128                 return EBADMEM;
00129         
00130         *packet_dimension = packet_dimensions_find(packet_dimensions,
00131             device_id);
00132         if (!*packet_dimension) {
00133                 /* Ask for and remember them if not found */
00134                 *packet_dimension = malloc(sizeof(**packet_dimension));
00135                 if(!*packet_dimension)
00136                         return ENOMEM;
00137                 
00138                 rc = ip_packet_size_req(ip_phone, device_id, *packet_dimension);
00139                 if (rc != EOK) {
00140                         free(*packet_dimension);
00141                         return rc;
00142                 }
00143                 
00144                 rc = packet_dimensions_add(packet_dimensions, device_id,
00145                     *packet_dimension);
00146                 if (rc < 0) {
00147                         free(*packet_dimension);
00148                         return rc;
00149                 }
00150         }
00151         
00152         return EOK;
00153 }
00154 
00163 int
00164 tl_update_ip_packet_dimension(packet_dimensions_t *packet_dimensions,
00165     device_id_t device_id, size_t content)
00166 {
00167         packet_dimension_t *packet_dimension;
00168 
00169         packet_dimension = packet_dimensions_find(packet_dimensions, device_id);
00170         if (!packet_dimension)
00171                 return ENOENT;
00172 
00173         packet_dimension->content = content;
00174 
00175         if (device_id != DEVICE_INVALID_ID) {
00176                 packet_dimension = packet_dimensions_find(packet_dimensions,
00177                     DEVICE_INVALID_ID);
00178 
00179                 if (packet_dimension) {
00180                         if (packet_dimension->content >= content)
00181                                 packet_dimension->content = content;
00182                         else
00183                                 packet_dimensions_exclude(packet_dimensions,
00184                                     DEVICE_INVALID_ID, free);
00185                 }
00186         }
00187 
00188         return EOK;
00189 }
00190 
00203 int tl_set_address_port(struct sockaddr * addr, int addrlen, uint16_t port)
00204 {
00205         struct sockaddr_in *address_in;
00206         struct sockaddr_in6 *address_in6;
00207         size_t length;
00208 
00209         if (addrlen < 0)
00210                 return EINVAL;
00211         
00212         length = (size_t) addrlen;
00213         if (length < sizeof(struct sockaddr))
00214                 return EINVAL;
00215 
00216         switch (addr->sa_family) {
00217         case AF_INET:
00218                 if (length != sizeof(struct sockaddr_in))
00219                         return EINVAL;
00220                 address_in = (struct sockaddr_in *) addr;
00221                 address_in->sin_port = htons(port);
00222                 return EOK;
00223         
00224         case AF_INET6:
00225                 if (length != sizeof(struct sockaddr_in6))
00226                                 return EINVAL;
00227                 address_in6 = (struct sockaddr_in6 *) addr;
00228                 address_in6->sin6_port = htons(port);
00229                 return EOK;
00230         
00231         default:
00232                 return EAFNOSUPPORT;
00233         }
00234 }
00235 
00249 int
00250 tl_prepare_icmp_packet(int packet_phone, int icmp_phone, packet_t *packet,
00251     services_t error)
00252 {
00253         packet_t *next;
00254         uint8_t *src;
00255         int length;
00256 
00257         /* Detach the first packet and release the others */
00258         next = pq_detach(packet);
00259         if (next)
00260                 pq_release_remote(packet_phone, packet_get_id(next));
00261         
00262         length = packet_get_addr(packet, &src, NULL);
00263         if ((length > 0) && (!error) && (icmp_phone >= 0) &&
00264             /*
00265              * Set both addresses to the source one (avoids the source address
00266              * deletion before setting the destination one)
00267              */
00268             (packet_set_addr(packet, src, src, (size_t) length) == EOK)) {
00269                 return EOK;
00270         } else
00271                 pq_release_remote(packet_phone, packet_get_id(packet));
00272 
00273         return ENOENT;
00274 }
00275 
00290 int
00291 tl_socket_read_packet_data(int packet_phone, packet_t **packet, size_t prefix,
00292     const packet_dimension_t *dimension, const struct sockaddr *addr,
00293     socklen_t addrlen)
00294 {
00295         ipc_callid_t callid;
00296         size_t length;
00297         void *data;
00298         int rc;
00299 
00300         if (!dimension)
00301                 return EINVAL;
00302 
00303         /* Get the data length */
00304         if (!async_data_write_receive(&callid, &length))
00305                 return EINVAL;
00306 
00307         /* Get a new packet */
00308         *packet = packet_get_4_remote(packet_phone, length, dimension->addr_len,
00309             prefix + dimension->prefix, dimension->suffix);
00310         if (!packet)
00311                 return ENOMEM;
00312 
00313         /* Allocate space in the packet */
00314         data = packet_suffix(*packet, length);
00315         if (!data) {
00316                 pq_release_remote(packet_phone, packet_get_id(*packet));
00317                 return ENOMEM;
00318         }
00319 
00320         /* Read the data into the packet */
00321         rc = async_data_write_finalize(callid, data, length);
00322         if (rc != EOK) {
00323                 pq_release_remote(packet_phone, packet_get_id(*packet));
00324                 return rc;
00325         }
00326         
00327         /* Set the packet destination address */
00328         rc = packet_set_addr(*packet, NULL, (uint8_t *) addr, addrlen);
00329         if (rc != EOK) {
00330                 pq_release_remote(packet_phone, packet_get_id(*packet));
00331                 return rc;
00332         }
00333 
00334         return (int) length;
00335 }
00336 

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