// Ada Milter API, a binding to Libmilter, the Sendmail mail filtering API // Copyright 2012 - 2013 B. Persson, Bjorn@Rombobeorn.se // // This library is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License version 3, as published // by the Free Software Foundation. // This file contains helper functions for extracting address data from a // sockaddr, because trying to access the fields of sockaddr structures from // Ada in a portable way would get ugly fast. #include #include #include #include #include // constants exported by milter_api.adb: extern const uint8_t milter_api_address_type_ipv4; extern const uint8_t milter_api_address_type_ipv6; extern const uint8_t milter_api_address_type_unknown; uint8_t milter_api_address_type(struct sockaddr const* const endpoint) // milter_api_address_type returns a code to tell which type of address // endpoint contains. { if(endpoint->sa_family == AF_INET) { return milter_api_address_type_ipv4; } else if(endpoint->sa_family == AF_INET6) { return milter_api_address_type_ipv6; } else { return milter_api_address_type_unknown; } } void milter_api_ipv4_address(struct sockaddr_in const* const endpoint, // in uint8_t* const buffer) // out // milter_api_ipv4_address copies the IPv4 address from endpoint to buffer. // buffer must be 4 bytes long. { memcpy(buffer, &endpoint->sin_addr, 4); } void milter_api_ipv6_address(struct sockaddr_in6 const* const endpoint, // in uint8_t* const buffer) // out // milter_api_ipv6_address copies the IPv6 address from endpoint to buffer. // buffer must be 16 bytes long. { memcpy(buffer, &endpoint->sin6_addr, 16); } void milter_api_address_string(struct sockaddr const* const endpoint, // in char* const buffer, // out const uint8_t size) // in // milter_api_address_string writes in buffer a textual representation of the // IP address in endpoint. size is the length of buffer in bytes. { char const* result = NULL; if(endpoint->sa_family == AF_INET) { result = inet_ntop(endpoint->sa_family, &((struct sockaddr_in const*)endpoint)->sin_addr, buffer, size); } else if(endpoint->sa_family == AF_INET6) { result = inet_ntop(endpoint->sa_family, &((struct sockaddr_in6 const*)endpoint)->sin6_addr, buffer, size); } if(result == NULL) { strncpy(buffer, "(error in address conversion)", size); buffer[size - 1] = '\0'; } } uint16_t milter_api_port(struct sockaddr const* const endpoint) // milter_api_port returns (in host byte order) the port number in endpoint. { if(endpoint->sa_family == AF_INET) { return ntohs(((struct sockaddr_in const*)endpoint)->sin_port); } else if(endpoint->sa_family == AF_INET6) { return ntohs(((struct sockaddr_in6 const*)endpoint)->sin6_port); } else { return 0; } }