2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * From: @(#)common.c 8.5 (Berkeley) 4/28/95
36 * $FreeBSD: src/usr.sbin/lpr/common_source/net.c,v 1.3.2.4 2001/06/25 01:00:56 gad Exp $
39 #include <sys/param.h>
40 #include <sys/socket.h>
45 #include <netinet/in.h>
46 #include <arpa/inet.h>
49 #include <dirent.h> /* required for lp.h, not used here */
59 #include "pathnames.h"
62 * 'local_host' is always the hostname of the machine which is running
63 * lpr (lpd, whatever), while 'from_host' either points at 'local_host'
64 * or points at a different buffer when receiving a job from a remote
65 * machine (and that buffer has the hostname of that remote machine).
67 char local_host
[MAXHOSTNAMELEN
]; /* host running lpd/lpr */
68 const char *from_host
= local_host
; /* client's machine name */
69 const char *from_ip
= ""; /* client machine's IP address */
72 u_char family
= PF_UNSPEC
;
74 u_char family
= PF_INET
;
77 extern uid_t uid
, euid
;
80 * Create a TCP connection to host "rhost" at port "rport".
81 * If rport == 0, then use the printer service port.
82 * Most of this code comes from rcmd.c.
85 getport(const struct printer
*pp
, const char *rhost
, int rport
)
87 struct addrinfo hints
, *res
, *ai
;
88 int s
, timo
= 1, lport
= IPPORT_RESERVED
- 1;
92 * Get the host address and port number to connect to.
95 fatal(pp
, "no remote host to connect to");
96 memset(&hints
, 0, sizeof(hints
));
97 hints
.ai_family
= family
;
98 hints
.ai_socktype
= SOCK_STREAM
;
99 hints
.ai_protocol
= 0;
100 err
= getaddrinfo(rhost
, (rport
== 0 ? "printer" : NULL
),
103 fatal(pp
, "%s\n", gai_strerror(err
));
105 ((struct sockaddr_in
*) res
->ai_addr
)->sin_port
= htons(rport
);
108 * Try connecting to the server.
113 s
= rresvport_af(&lport
, ai
->ai_family
);
116 if (errno
!= EAGAIN
) {
121 if (refused
&& timo
<= 16) {
132 if (connect(s
, ai
->ai_addr
, ai
->ai_addrlen
) < 0) {
137 * This used to decrement lport, but the current semantics
138 * of rresvport do not provide such a function (in fact,
139 * rresvport should guarantee that the chosen port will
140 * never result in an EADDRINUSE).
142 if (errno
== EADDRINUSE
) {
146 if (errno
== ECONNREFUSED
)
149 if (ai
->ai_next
!= NULL
) {
153 if (refused
&& timo
<= 16) {
168 * Figure out whether the local machine is the same
169 * as the remote machine (RM) entry (if it exists).
170 * We do this by counting the intersection of our
171 * address list and theirs. This is better than the
172 * old method (comparing the canonical names), as it
173 * allows load-sharing between multiple print servers.
174 * The return value is an error message which must be
178 checkremote(struct printer
*pp
)
180 char lclhost
[MAXHOSTNAMELEN
];
181 struct addrinfo hints
, *local_res
, *remote_res
, *lr
, *rr
;
183 int ncommonaddrs
, error
;
184 char h1
[NI_MAXHOST
], h2
[NI_MAXHOST
];
186 if (!pp
->rp_matches_local
) { /* Remote printer doesn't match local */
191 pp
->remote
= 0; /* assume printer is local */
192 if (pp
->remote_host
== NULL
)
195 /* get the addresses of the local host */
196 gethostname(lclhost
, sizeof(lclhost
));
197 lclhost
[sizeof(lclhost
) - 1] = '\0';
199 memset(&hints
, 0, sizeof(hints
));
200 hints
.ai_family
= family
;
201 hints
.ai_socktype
= SOCK_STREAM
;
202 hints
.ai_flags
= AI_PASSIVE
;
203 if ((error
= getaddrinfo(lclhost
, NULL
, &hints
, &local_res
)) != 0) {
204 asprintf(&err
, "unable to get official name "
205 "for local machine %s: %s",
206 lclhost
, gai_strerror(error
));
210 /* get the official name of RM */
211 memset(&hints
, 0, sizeof(hints
));
212 hints
.ai_family
= family
;
213 hints
.ai_socktype
= SOCK_STREAM
;
214 hints
.ai_flags
= AI_PASSIVE
;
215 if ((error
= getaddrinfo(pp
->remote_host
, NULL
,
216 &hints
, &remote_res
)) != 0) {
217 asprintf(&err
, "unable to get address list for "
218 "remote machine %s: %s",
219 pp
->remote_host
, gai_strerror(error
));
220 freeaddrinfo(local_res
);
225 for (lr
= local_res
; lr
; lr
= lr
->ai_next
) {
227 if (getnameinfo(lr
->ai_addr
, lr
->ai_addrlen
, h1
, sizeof(h1
),
228 NULL
, 0, NI_NUMERICHOST
| NI_WITHSCOPEID
) != 0)
230 for (rr
= remote_res
; rr
; rr
= rr
->ai_next
) {
232 if (getnameinfo(rr
->ai_addr
, rr
->ai_addrlen
,
233 h2
, sizeof(h2
), NULL
, 0,
234 NI_NUMERICHOST
| NI_WITHSCOPEID
) != 0)
236 if (strcmp(h1
, h2
) == 0)
242 * if the two hosts do not share at least one IP address
243 * then the printer must be remote.
245 if (ncommonaddrs
== 0)
247 freeaddrinfo(local_res
);
248 freeaddrinfo(remote_res
);
253 * This isn't really network-related, but it's used here to write
254 * multi-part strings onto sockets without using stdio. Return
255 * values are as for writev(2).
258 writel(int strm
, ...)
264 struct iovec iov
[NIOV
], *iovp
= iov
;
267 /* first count them */
271 cp
= va_arg(ap
, char *);
275 n
--; /* correct for count of trailing null */
278 iovp
= malloc(n
* sizeof *iovp
);
283 /* now make up iovec and send */
285 for (i
= 0; i
< n
; i
++) {
286 iovp
[i
].iov_base
= va_arg(ap
, char *);
287 iovp
[i
].iov_len
= strlen(iovp
[i
].iov_base
);
290 retval
= writev(strm
, iovp
, n
);