1 /*
2 ** ident.c	High-level calls to the ident lib
3 **
4 ** Author: P�r Emanuelsson <pell@lysator.liu.se>
5 ** Hacked by: Peter Eriksson <pen@lysator.liu.se>
6 ** Updated by: R�mi Denis-Courmont <rdenis@simphalempin.com>
7 */
8 
9 #if HAVE_CONFIG_H
10 # include "config.h"
11 #endif
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 
18 #if HAVE_SYS_TYPES_H
19 # include <sys/types.h>
20 #endif
21 #if HAVE_SYS_SOCKET_H
22 # include <sys/socket.h>
23 #endif
24 #if HAVE_NETINET_IN_H
25 # include <netinet/in.h>
26 #endif
27 
28 #define IN_LIBIDENT_SRC
29 #include "ident.h"
30 
31 
32 
33 
34 
35 /* Do a complete ident query and return result */
36 
ident_lookup(int fd,int timeout)37 IDENT *ident_lookup (int fd, int timeout)
38 {
39     struct sockaddr_storage localaddr, remoteaddr;
40     int len;
41 
42     len = sizeof(remoteaddr);
43     if (getpeername(fd, (struct sockaddr*)&remoteaddr, &len) < 0)
44 	return 0;
45 
46     len = sizeof(localaddr);
47     if (getsockname(fd, (struct sockaddr *)&localaddr, &len) < 0)
48 	return 0;
49 
50     return ident_query_addr((struct sockaddr *)&localaddr,
51 				(struct sockaddr *)&remoteaddr, timeout);
52 }
53 
54 
ident_query(const struct in_addr * laddr,const struct in_addr * faddr,int lport,int rport,int timeout)55 IDENT *ident_query (const struct in_addr *laddr, const struct in_addr *faddr,
56 			int lport, int rport, int timeout)
57 {
58     struct sockaddr_in lsockaddr, fsockaddr;
59 
60     memset(&lsockaddr, 0, sizeof(lsockaddr));
61     lsockaddr.sin_family = AF_INET;
62 #if HAVE_SA_LEN
63     lsockaddr.sin_len = sizeof(lsockaddr);
64 #endif
65     lsockaddr.sin_addr.s_addr = laddr->s_addr;
66     lsockaddr.sin_port = lport;
67 
68     memcpy(&fsockaddr, &lsockaddr, sizeof(fsockaddr));
69     fsockaddr.sin_addr.s_addr = faddr->s_addr;
70     fsockaddr.sin_port = rport;
71 
72     return ident_query_addr((struct sockaddr *)&lsockaddr,
73 				(struct sockaddr *)&fsockaddr, timeout);
74 }
75 
ident_query_addr(const struct sockaddr * laddr,const struct sockaddr * raddr,int timeout)76 IDENT *ident_query_addr (const struct sockaddr *laddr,
77 				const struct sockaddr *raddr, int timeout)
78 {
79     int res, lport, rport;
80     ident_t *id;
81     struct timeval timout;
82     IDENT *ident = NULL;
83 
84     switch (laddr->sa_family)
85     {
86       case AF_INET:
87         /* We assume that both addresses are in the same family. */
88         lport = ntohs(((struct sockaddr_in *)laddr)->sin_port);
89         rport = ntohs(((struct sockaddr_in *)raddr)->sin_port);
90         break;
91 
92 #ifdef AF_INET6
93       case AF_INET6:
94         lport = ntohs(((struct sockaddr_in6 *)laddr)->sin6_port);
95         rport = ntohs(((struct sockaddr_in6 *)raddr)->sin6_port);
96         break;
97 #endif
98 
99       default:
100         return NULL;
101     }
102 
103     timout.tv_sec = timeout;
104     timout.tv_usec = 0;
105 
106     id = id_open_addr(laddr, raddr, (timeout) ? &timout : NULL);
107     if (id == NULL)
108     {
109 	errno = EINVAL;
110 	return NULL;
111     }
112 
113     if (timeout)
114 	res = id_query(id, rport, lport, &timout);
115     else
116 	res = id_query(id, rport, lport, (struct timeval *) 0);
117 
118     if (res < 0)
119     {
120 	id_close(id);
121 	return NULL;
122     }
123 
124     ident = (IDENT *) malloc(sizeof(IDENT));
125     if (ident == NULL) {
126 	id_close(id);
127 	return NULL;
128     }
129 
130     res = id_parse(id, (timeout) ? &timout : NULL, &ident->lport,
131 		   &ident->fport, &ident->identifier, &ident->opsys,
132 		   &ident->charset);
133 
134     if (res != 1)
135     {
136 	free(ident);
137 	id_close(id);
138 	return NULL;
139     }
140 
141     id_close(id);
142     return ident;			/* At last! */
143 }
144 
145 
ident_id(int fd,int timeout)146 char *ident_id (int fd, int timeout)
147 {
148     IDENT *ident;
149     char *id = NULL;
150 
151     ident = ident_lookup(fd, timeout);
152     if (ident && ident->identifier && *ident->identifier)
153     {
154 	id = id_strdup(ident->identifier);
155 	if (id == NULL)
156 	    return NULL;
157     }
158 
159     ident_free(ident);
160     return id;
161 }
162 
163 
ident_free(IDENT * id)164 void ident_free (IDENT * id)
165 {
166     if (id != NULL)
167     {
168         if (id->identifier)
169 	    free(id->identifier);
170 	if (id->opsys)
171 	    free(id->opsys);
172 	if (id->charset)
173 	    free(id->charset);
174 	free(id);
175     }
176 }
177 
178 const char *id_version = PACKAGE_VERSION;
179 
180