Solved

Perl Socket Problem

Posted on 1997-08-03
3
558 Views
Last Modified: 2008-03-03
I want to be able to change my passwd on the server "ebs2.eecs" from my machine "ebs1.eecs" using sockets.
ebs2.eecs has an entry for the program under /etc/services and /etc/inetd.conf. On calling the program from ebs1.eecs I do get Testing.. as the output but nothing further happens.

1) What do I need to do to get this to work?
2) How come I don't get an output for $name when I call the
   client prog. with an output?

The client program that runs on my machine "ebs1.eecs"

#!/usr/sww/bin/perl
# passwd.client

$AF_INET = 2;
$SOCK_STREAM = 1;
$sockaddr = 'S n a4 x8';

chop ($user = `whoami`) unless $user;

$port = 1997;
$host = 'ebs2.eecs';

($n, $a, $proto) = getprotobyname('tcp');
($n, $a, $t, $l, @thisaddr) = gethostbyname('localhost');
($n, $a, $t, $l, @thataddr) = gethostbyname($host);

$this = pack($sockaddr, $AF_INET, 0, $thisaddr);
$that = pack($sockaddr, $AF_INET, $port, @thataddr);

socket(S, $AF_INET, $SOCK_STREAM, $proto) || die "Can't open socket!\n";
bind(S, $this) || die "Couldn't bind a new socket!\n";
connect(S, $that) || die "Couldn't connect to host $host, port $port!\n";

select(S); $| = 1; select(STDOUT);

print S "$user\n";  ##Pass the user to the server                                  passwd.answerd prog

while (<S>) {
    print;
}

---------------------------------
The server prog on "ebs2.eecs"
---------------------------------

#!/usr/sww/bin/perl
# passwd.server

$ENV{'PATH'} = '/bin:/etc:/etc/bin:/usr/bin:/usr/ucb:/usr/local/bin';
print "Testing.. \n" ;
local($name) = @_ ;

$AF_INET = 2;
$SOCK_STREAM = 1;
$sockaddr = 'S n a4 x8';

$port = 1997;

($n, $a, $t, $l, @thisaddr) = gethostbyname($host);
($n, $a, $proto) = getprotobyname('tcp');
$thisport = pack($sockaddr,$AF_INET,$port,$thisaddr);
socket(S, $AF_INET, $SOCK_STREAM, $proto) || die "Can't open socket!";
bind(S,$thisport) || die "Cannot bind socket \n" ;
listen(S,5) || die "Cannot listen socket \n" ;
for(;;)
{
  accept(NS,S) || die "Cannot accept socket\n" ;
  system "/bin/passwd" ;
  close NS;
}



0
Comment
Question by:monish
  • 2
3 Comments
 
LVL 1

Accepted Solution

by:
icculus earned 50 total points
ID: 1205181
The first thing I would recommend doing is changing the
socket handling techniques you are using to use the Socket
module provided with perl5.002 and higher.

#
# Sample code to get the server operating (assumes
# perl5.002 is installed at /usr/local/bin/perl):
#

#!/usr/local/bin/perl

require 5.002;
use Socket;
use Fcntl;
use POSIX;

$port = 1997;
$proto = getprotobyname('tcp');

# Open the socket, set socket options for reuse

socket(Server, PF_INET, SOCK_STREAM, $proto) or die "socket: $!";
setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die "setsockopt: $!";
setsockopt(Server, SOL_SOCKET, SO_LINGER, 0);

# bind socket, allowing 1 connection at a time, set
# non-blocking io

bind(Server, sockaddr_in($port, INADDR_ANY)) or die "bind: $!";
fcntl(Server, F_SETFL, O_NONBLOCK);
listen(Server, 1) or die "listen: $!";

for (; $paddr = accept(Client,Server); close Client){

   # Ok, the server has a connection which can now
   # be referenced as the filehandle Client.
   # Expect input in the form: user tab pwd
   # Warning: You will likely need to strip some
   # extra characters found at the end of the string.
   # You can do this by checking for non-null characters.

   my ($input) = <Client>;
   my ($user, $pwd) = (split("\t", $input));

   # You will likely need to reorganize the way you
   # interact wth the passwd command, see below.  
   # after executing pwd command the for loop closes
   # the connection.
}

#
# Sample Code for Interacting with passwd command
#

open(PWD, "|/bin/passwd $user");
while(<PWD>){

   # You know what the password command prompts for
   # and you need to print to it in the order that
   # it requires.

   print PWD "${pwd}\n"; # Password to change to
   print PWD "${pwd}\n"; # Verification of new password
}
close(PWD);

#
# Sample Client Code. Assumes same perl call and
# same same modules used
#

$remote  = "hostname.ext";
$port    = 1997
$iaddr   = inet_aton($remote) || return 0;
$paddr   = sockaddr_in($port, $iaddr);

# Open the scket
socket(SOCK, PF_INET, SOCK_STREAM, $proto);  
# Call up the server
connect(SOCK, $paddr);

while(<SOCK>){
   # Print the user name and password, tab-delim
   # The server should expect to read a string, tab, then
   # string.

   print "${user}\t${pwd}\n";

   # The server will close the connection when it is
   # done, this should end the while loop.
}

This should give you a basis for converting to the
Socket module, it is much better than using the old
socket handling techniques, which do not work on all
platforms. This example also shows you how to interact
with the password command through a named pipe. This is
also a good way of handling this...

Hope this helps!
Andy
0
 

Author Comment

by:monish
ID: 1205182
I tried your example. I see the server process start up at
the server "ebs2" and get some error checking output on "ebs1".  
The following is the output I get back on ebs1 when I run the program :

CHECK C1
CHECK C2
CHECK C3
CHECK S1
CHECK C3
CHECK S2
CHECK C3
CHECK S3
bind: Address already in useCHECK C4

So it never goes pass the following line on the server :
bind(Server, $port)                     or die "bind: $!" ;

Any clues on how I can get the client and Server to talk and fix this ? Thanks.


===============================================================
The client code on ebs1 :

#!/usr/local/bin/perl5
require 5.002;
use strict;
use Socket;
use Fcntl;
use POSIX;

my $user = `whoami` ;
my ($remote,$port,$iaddr,$paddr,$proto,$line);

$remote = "ebs2.eecs.berkeley.edu";
$port = 1995 ;

$iaddr = inet_aton($remote) or print "ERROR1\n" ;
$paddr = sockaddr_in($port, $iaddr);

# Open the socket
$proto = getprotobyname('tcp') ;
socket(SOCK, PF_INET, SOCK_STREAM, $proto) or die "Could'nt create socket";

# Call up the server
connect(SOCK, $paddr) or die "Couldn't connect socket";

print "CHECK C1\n" ;
##select(SOCK); $| = 1; select(STDOUT);
print "CHECK C2\n" ;

while(<SOCK>)
{
    print "CHECK C3\n" ;
    print ;
}
print "CHECK C4\n" ;
close (SOCK) || die "Couldn't close socket\n";
exit ;

====================================================
The server code on ebs2 :

#!/usr/local/bin/perl5
require 5.002;
use strict;
use Socket;
use Carp;
use Fcntl;
use POSIX;

print "CHECK S1\n" ;
my $port = 1995;
my $proto = getprotobyname('tcp');

socket(Server, PF_INET, SOCK_STREAM, $proto) or die "socket: $!" ;
print "CHECK S2\n" ;
setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("1",1))       or die "setsockopt: $!";
print "CHECK S3\n" ;
#bind(Server,sockaddr_in($port,INADDR_ANY)) or print "bind: $!" ;
bind(Server, $port)                     or die "bind: $!" ;
print "CHECK S4\n" ;
listen(Server,SOMAXCONN)                or die "listen: $!" ;

my $paddr;
for ( ; $paddr = accept(Client,Server); close Client)
{
  my($port, $iaddr) = sockaddr_in($paddr);
  my $name = gethostbyaddr($iaddr,AF_INET);
  print Client "Hello there, $name \n";
}

=========================================================








0
 
LVL 1

Expert Comment

by:icculus
ID: 1205183
Ok, the bind: Address already in use indicates that either
the port you are using is already bound by another program,
or it is bound by the current program but has not been.

For example, if you run the program and then kill it, the
port will remain bound for a few minutes. I have this problem
with a proxy server I use, it takes about 5 full minutes
before I can run it again after the server dies. Give it
some time and then try again. I know this sucks and is quite
a hassle when debugging but it happens... *sigh*

-Andy
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
perl exit code 2 244
Exchange 2010 Transport Rule Regex 28 88
ppm conversion to curl on a module install 8 74
File Find regex problem 4 58
On Microsoft Windows, if  when you click or type the name of a .pl file, you get an error "is not recognized as an internal or external command, operable program or batch file", then this means you do not have the .pl file extension associated with …
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now