00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
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                 
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         
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 
00266 
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         
00304         if (!async_data_write_receive(&callid, &length))
00305                 return EINVAL;
00306 
00307         
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         
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         
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         
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