17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*022ba35cSjacobs * Common Development and Distribution License (the "License"). 6*022ba35cSjacobs * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate /* 23*022ba35cSjacobs * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*022ba35cSjacobs * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <stdio.h> 307c478bd9Sstevel@tonic-gate #include <stdlib.h> 317c478bd9Sstevel@tonic-gate #include <libintl.h> 327c478bd9Sstevel@tonic-gate #include <signal.h> 337c478bd9Sstevel@tonic-gate #include <errno.h> 347c478bd9Sstevel@tonic-gate #include <string.h> 357c478bd9Sstevel@tonic-gate #include <strings.h> 367c478bd9Sstevel@tonic-gate #include <syslog.h> 377c478bd9Sstevel@tonic-gate #include <unistd.h> 387c478bd9Sstevel@tonic-gate #include <sys/types.h> 397c478bd9Sstevel@tonic-gate #include <fcntl.h> 407c478bd9Sstevel@tonic-gate #include <sys/socket.h> 417c478bd9Sstevel@tonic-gate #include <netinet/in.h> 427c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 437c478bd9Sstevel@tonic-gate #include <netdb.h> 447c478bd9Sstevel@tonic-gate #include "netpr.h" 457c478bd9Sstevel@tonic-gate #include "netdebug.h" 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate #define MAX_NLPS 60 /* Max no. loops in while */ 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate np_tcpjob_t * 507c478bd9Sstevel@tonic-gate create_tcp_job(np_job_t *genjob, int filesize) 517c478bd9Sstevel@tonic-gate { 527c478bd9Sstevel@tonic-gate np_tcpjob_t *tcpjob; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate if (genjob == NULL) 557c478bd9Sstevel@tonic-gate return (NULL); 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate tcpjob = (np_tcpjob_t *)malloc(sizeof (np_tcpjob_t)); 587c478bd9Sstevel@tonic-gate ASSERT(tcpjob, MALLOC_ERR); 597c478bd9Sstevel@tonic-gate (void) memset(tcpjob, 0, sizeof (np_tcpjob_t)); 607c478bd9Sstevel@tonic-gate 61*022ba35cSjacobs tcpjob->np_port = "9100"; 627c478bd9Sstevel@tonic-gate tcpjob->gen_data = genjob; 637c478bd9Sstevel@tonic-gate tcpjob->gen_data->filesize = filesize; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate return (tcpjob); 667c478bd9Sstevel@tonic-gate } 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate int 697c478bd9Sstevel@tonic-gate tcp_open(char *dest, np_tcpjob_t *tcpjob, int timeout) 707c478bd9Sstevel@tonic-gate { 717c478bd9Sstevel@tonic-gate struct hostent *hp; 727c478bd9Sstevel@tonic-gate struct sockaddr_in6 serv_addr; 737c478bd9Sstevel@tonic-gate int s, 747c478bd9Sstevel@tonic-gate err, 757c478bd9Sstevel@tonic-gate error_num; 767c478bd9Sstevel@tonic-gate unsigned timo = 1; 777c478bd9Sstevel@tonic-gate int retry; 787c478bd9Sstevel@tonic-gate int rtnerr; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* 817c478bd9Sstevel@tonic-gate * Get the host address and port number to connect to. 827c478bd9Sstevel@tonic-gate */ 837c478bd9Sstevel@tonic-gate if (dest == NULL) { 847c478bd9Sstevel@tonic-gate return (-1); 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate if ((hp = (getipnodebyname(dest, AF_INET6, AI_DEFAULT, 887c478bd9Sstevel@tonic-gate &error_num))) == NULL) { 897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 907c478bd9Sstevel@tonic-gate gettext("Netpr: System call getipnodebyname fails\n")); 917c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "System call getipnodebyname fails " 927c478bd9Sstevel@tonic-gate "getipnodebyname() returned %d", error_num); 937c478bd9Sstevel@tonic-gate return (-1); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate (void) memset(&serv_addr, 0, sizeof (struct sockaddr_in6)); 977c478bd9Sstevel@tonic-gate bcopy(hp->h_addr, (caddr_t)&serv_addr.sin6_addr, hp->h_length); 987c478bd9Sstevel@tonic-gate serv_addr.sin6_family = hp->h_addrtype; 997c478bd9Sstevel@tonic-gate serv_addr.sin6_port = (int)htons(atoi(tcpjob->np_port)); 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate do { 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate retry = 0; 1047c478bd9Sstevel@tonic-gate rtnerr = 0; 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * Try connecting to the printer. 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate s = socket(PF_INET6, SOCK_STREAM, 0); 1097c478bd9Sstevel@tonic-gate if (s < 0) { 1107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1117c478bd9Sstevel@tonic-gate gettext("Netpr: System call socket fails\n")); 1127c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "System call socket fails"); 1137c478bd9Sstevel@tonic-gate rtnerr = -1; 1147c478bd9Sstevel@tonic-gate } else { 1157c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, null_sighandler); 1167c478bd9Sstevel@tonic-gate (void) alarm(timeout); 1177c478bd9Sstevel@tonic-gate if (connect(s, (struct sockaddr *)&serv_addr, 1187c478bd9Sstevel@tonic-gate sizeof (serv_addr)) < 0) { 1197c478bd9Sstevel@tonic-gate err = errno; 1207c478bd9Sstevel@tonic-gate (void) alarm(0); 1217c478bd9Sstevel@tonic-gate errno = err; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate if (errno == ECONNREFUSED && timo <= 16) { 1247c478bd9Sstevel@tonic-gate (void) sleep(timo); 1257c478bd9Sstevel@tonic-gate timo *= 2; 1267c478bd9Sstevel@tonic-gate retry++; 1277c478bd9Sstevel@tonic-gate } else { 1287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1297c478bd9Sstevel@tonic-gate gettext("Netpr: Cannot connect to printer\n")); 1307c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "Cannot connect to printer"); 1317c478bd9Sstevel@tonic-gate rtnerr = -1; 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate /* The connect on this socket failed; close it */ 1347c478bd9Sstevel@tonic-gate (void) close(s); 1357c478bd9Sstevel@tonic-gate } else 1367c478bd9Sstevel@tonic-gate (void) alarm(0); 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate } while (retry); 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate return ((rtnerr) ? rtnerr : s); 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate int 1467c478bd9Sstevel@tonic-gate tcp_print(int sockfd, caddr_t pa, np_tcpjob_t *tcpjob) 1477c478bd9Sstevel@tonic-gate { 1487c478bd9Sstevel@tonic-gate char c; 1497c478bd9Sstevel@tonic-gate int xfer; 1507c478bd9Sstevel@tonic-gate char buf[BUFSIZ + 1]; 1517c478bd9Sstevel@tonic-gate int nr = 0; 1527c478bd9Sstevel@tonic-gate int ctr = 0; 1537c478bd9Sstevel@tonic-gate int msg_given = 0; 1547c478bd9Sstevel@tonic-gate int nlps = 0; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate if ((xfer = xfer_file(sockfd, pa, 1577c478bd9Sstevel@tonic-gate tcpjob->gen_data->filesize, tcpjob->gen_data->timeout)) < 0) { 1587c478bd9Sstevel@tonic-gate return (xfer); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate if ((shutdown(sockfd, 1)) != 0) { 1627c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1637c478bd9Sstevel@tonic-gate gettext("Netpr: System error: possible loss of data\n")); 1647c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 1657c478bd9Sstevel@tonic-gate "shutdown error; possible loss of data"); 1667c478bd9Sstevel@tonic-gate return (E_SYSTEM_ERROR); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* read in single character ack or msg from printer */ 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate (void) memset(buf, 0, BUFSIZ + 1); 1737c478bd9Sstevel@tonic-gate while (ctr < BUFSIZ) { 1747c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, null_sighandler); 1757c478bd9Sstevel@tonic-gate (void) alarm(2); 1767c478bd9Sstevel@tonic-gate errno = 0; 1777c478bd9Sstevel@tonic-gate nr = read(sockfd, &c, 1); 1787c478bd9Sstevel@tonic-gate (void) alarm(0); 1797c478bd9Sstevel@tonic-gate if (errno == EINTR) { 1807c478bd9Sstevel@tonic-gate if (msg_given == 0) { 1817c478bd9Sstevel@tonic-gate tell_lptell(ERRORMSG, 1827c478bd9Sstevel@tonic-gate gettext("Printer not responding;" \ 1837c478bd9Sstevel@tonic-gate "Either warming up or needs attention\n")); 1847c478bd9Sstevel@tonic-gate msg_given++; 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate /* if no ACK received, do not loop forever */ 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate if (nlps++ >= MAX_NLPS) { 1907c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "No final ack received"); 1917c478bd9Sstevel@tonic-gate break; 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate } else { 1947c478bd9Sstevel@tonic-gate if ((buf[ctr++] = c) == '\n' || (nr == 0)) 1957c478bd9Sstevel@tonic-gate break; 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate if (ctr > 1) 1997c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "Message from tcp printer on read: %s", 2007c478bd9Sstevel@tonic-gate buf); 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate if (msg_given && (nlps < MAX_NLPS)) { 2037c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Printer ok\n")); 2047c478bd9Sstevel@tonic-gate tell_lptell(OKMSG, "Current"); 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate return (E_SUCCESS); 2087c478bd9Sstevel@tonic-gate } 209