📄 agent_utils.c
字号:
/* $Id: agent_utils.c,v 1.13 2001/06/23 22:23:51 jm Exp $ * Independent help routines for FA and HA * * Dynamic hierarchial IP tunnel * Copyright (C) 1998-2001, Dynamics group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. */#include <stdlib.h>#include <syslog.h>#include <string.h>#include <errno.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include "agent_utils.h"#include "message.h"#include "rsa_dyn.h"#include "debug.h"#include "md5_mac.h"#include "binding.h"#include "util.h"#define DEBUG_FLAG 'u'/** * dynamics_do_rsa_encrypt: * @sk: pointer to session key * @sk_len: session key length in bytes * @pubkey: pointer to other end-point's public key extension * * Encrypt session key @sk (@sk_len bytes) for another FA using its public * key (@pubkey). This function allocates memory and the caller must take care * of releasing the returned memory area. * * Returns: * A pointer to initialized FA pubkey reply extension of %NULL on failure. */struct msg_key *dynamics_do_rsa_encrypt(unsigned char const *sk, int sk_len, const struct msg_key *pubkey){ unsigned int e_len; unsigned char *e_sk; struct msg_key *keyrep; e_sk = rsa_encrypt_session_key(sk, sk_len, MSG_KEY_DATA(pubkey), GET_KEY_LEN(pubkey), &e_len); if (e_sk == NULL || e_len <= 0 || e_len > (255 - SPI_LEN)) { DEBUG(DEBUG_FLAG, "RSA encryption failed\n"); if (e_sk != NULL) free(e_sk); return NULL; } keyrep = (struct msg_key *) malloc(sizeof(struct msg_key) + e_len); if (keyrep == NULL) { DEBUG(DEBUG_FLAG, "Not enough memory for keyrep\n"); } else { init_key_extension(keyrep, VENDOR_EXT_DYNAMICS_FA_PUBKEYREP, pubkey->spi, e_len); memcpy(MSG_KEY_DATA(keyrep), e_sk, e_len); } free(e_sk); return keyrep;}/** * dynamics_check_sendto: * @ret: The return value of a sendto system call or -2 if error was already * reported * @len: The number of bytes that was intended to be sent * by sendto() * @error: String to include in error message * * Prints an error message if len != ret. This function is meant * to be called after a sendto system call. * * Returns: 0 if there was no error in the original sendto call, * else -1 */intdynamics_check_sendto(int ret, int len, char *error){ if (ret == -2) return -1; /* send address not OK - already reported */ if (ret < 0) { syslog(LOG_INFO, "%s: sendto(%i/%i): %s", error, ret, len, strerror(errno)); DEBUG(DEBUG_FLAG, "%s: sendto(%i/%i): %s\n", error, ret, len, strerror(errno)); return -1; } else if (ret != len) { syslog(LOG_INFO, "%s: sendto: only %i/%i bytes sent", error, ret, len); DEBUG(DEBUG_FLAG, "%s: sendto: only %i/%i bytes sent\n", error, ret, len); return -1; } return 0;}/** * dynamics_open_udp_socket: * @socket_priority: Set the socket priority, -1 for default priority * @addr: If set, only listen to the given address * @port: Port number to listen to * @dev: If set, force the use of the given device * * Sets up a UDP socket with the IP_RECVTTL and IP_PKTINFO socket options; * see ip(7) for details. * If a socket priority is given, the SO_PRIORITY option is set. If * dev is non-NULL the socket is bound to the given device name with * SO_BINDTODEVICE. See socket(7) for details. * * Returns: If successful, the file descriptor for the socket, else -1 */intdynamics_open_udp_socket(int socket_priority, struct in_addr addr, short int port, char *dev){ struct sockaddr_in serv_addr; int s, one = 1; /* Socket for registration request and updates */ s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("socket"); return -1; } if (dev != NULL && setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, dev, IFNAMSIZ)) { DEBUG(DEBUG_FLAG, "dynamics_open_udp_socket - " "setsockopt(SOL_SOCKET, SO_BINDTODEVICE): %s\n", strerror(errno)); close(s); return -1; } /* bind the address and port to listen to registration * requests (usually UDP port 434) */ memset((char *) &serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = addr.s_addr; serv_addr.sin_port = htons(port); if (bind(s, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { char error[20]; snprintf(error, 20, "bind[UDP%d]", port); perror(error); close(s); return -1; } if (setsockopt(s, SOL_IP, IP_RECVTTL, (const void *)&one, sizeof(one)) < 0) { DEBUG(DEBUG_FLAG, "dynamics_open_udp_socket - setsockopt(SOL_IP, " "IP_RECVTTL): %s\n", strerror(errno)); /* continue without IP_RECVTTL */ } if (setsockopt(s, SOL_IP, IP_PKTINFO, (const void *)&one, sizeof(one)) < 0) { DEBUG(DEBUG_FLAG, "dynamics_open_udp_socket - setsockopt(SOL_IP, " "IP_PKTINFO): %s\n", strerror(errno)); /* continue without IP_PKTINFO */ } if (socket_priority > -1 && setsockopt(s, SOL_SOCKET, SO_PRIORITY, (const void *)&socket_priority, sizeof(socket_priority)) < 0) { DEBUG(DEBUG_FLAG, "dynamics_open_udp_socket - setsockopt SO_PRIORITY: " "%s\n", strerror(errno)); /* continue without SO_PRIORITY */ } DEBUG(DEBUG_FLAG, "Listening UDP on %s:%i dev[%s]\n", inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port), dev != NULL ? dev : "N/A"); return s;}/* glibc 2.1 seems to have more or less too strict checking of message length * bug? >= should be == ? * Well... using these routines from kernel headers.. */static struct cmsghdr * dynamics_cmsg_nxthdr2(void *__ctl, size_t __size, struct cmsghdr *__cmsg){ struct cmsghdr * __ptr; __ptr = (struct cmsghdr *) (((unsigned char *) __cmsg) + CMSG_ALIGN(__cmsg->cmsg_len)); if ((unsigned long) ((char *) (__ptr+1) - (char *) __ctl) > __size) return NULL; return __ptr;}struct cmsghdr * dynamics_cmsg_nxthdr(struct msghdr *__msg, struct cmsghdr *__cmsg){ return dynamics_cmsg_nxthdr2(__msg->msg_control, __msg->msg_controllen, __cmsg);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -