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