Openfire+Spark - Client X.509/PKI Certificate Support

Did anybody found something out? I’m still trying to fix this problem up. In case this will not work, does anybody have alternative ideas? I need to implement an encrpted and authenticated connection.

Thanks in advance

Daniel

OK, it’s hard to be sure, but I think I’ve got it “working.”

I could not get my simple login smack client working on :5223. Scanning through other forum postings noted that the Socket might not be right – try using the default SSL Socket:

   config.setSocketFactory(SSLSocketFactory.getDefault());

This moved me forward. However, the

So, with an empty client.truststore:

SocketAcceptorIoProcessor-1.0, fatal error: 80: problem unwrapping net record
java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
SocketAcceptorIoProcessor-1.0, SEND TLSv1 ALERT: fatal, description = internal_error
SocketAcceptorIoProcessor-1.0, WRITE: TLSv1 Alert, length = 2

valid client.truststore:

successful login; see client certificate in server’s debug output

HOWEVER The callback stuff appears not to be working – if I disable setting the default keystorePassword property, but have a CallbackHandler set, I still get:

Logging into tester@localhost
XMPPError connecting to localhost:5223.: remote-server-error(502) XMPPError connecting to localhost:5223.
– caused by: java.net.SocketException: password can’t be null
at org.jivesoftware.smack.XMPPConnection.connectUsingConfiguration(XMPPConnection. java:900)
at org.jivesoftware.smack.XMPPConnection.connect(XMPPConnection.java:1415)
at TestClient.main(TestClient.java:60)
Nested Exception:
java.net.SocketException: password can’t be null
at javax.net.ssl.DefaultSSLSocketFactory.createSocket(SSLSocketFactory.java:156)
at org.jivesoftware.smack.XMPPConnection.connectUsingConfiguration(XMPPConnection. java:888)
at org.jivesoftware.smack.XMPPConnection.connect(XMPPConnection.java:1415)
at TestClient.main(TestClient.java:60)

Presumably this is because the default SSLSocketFactory is not passing out to callbacks. However, I’ve been completely unsuccessful finding any more useful documentation regarding what SSLSocketFactory to use with Smack. Is there an openfire specific SocketFactory? One that works with TLS as well?

Likewise, trying to use TLS (instead of SSL) on :5222 (or even :5223, which probably isn’t expected to work) totally as we’ve seen before:

javax.net.ssl.SSLProtocolException: Handshake message sequence violation, 2
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.j ava:86)

So, at this point, nothing has really worked:
o The RPM installed a somehow-broken implementation such that the server would not even advertize valid CAs;
- the tar.gz (and .deb) did, but
o none of the clients really work with the callback stuff.
- since there’s some other stuff going on in Spark, it seems impossible to do anything but rely on the (broken?) callback handling.
o Of course, none of it works with TLS, only old-style SSL on :5223.

I still have to believe there is some other trick going on – or are the PCKS#11 handling class(es) different from the JKS handling ones? I.e., could there be a difference in the callback propogation code in the JKS-handling one(s)?


Also: why it’s trying to dial home:

2009.05.01 07:33:59 Retrying request
2009.05.01 07:33:59 Open connection to www.igniterealtime.org:80
2009.05.01 07:33:59 Closing the connection.
2009.05.01 07:33:59 Method retry handler returned false. Automatic recovery will not be attempted

I’m not sure. Can this be killed? Is it just the ‘check for updates’ piece?


My client is as follows, minus setting the properties to things like ‘tester’ and ‘localhost’:

public static void main(String[] args) {

    System.setProperty("javax.net.ssl.keyStore", KEYSTORE_PATH);
    System.setProperty("javax.net.ssl.trustStore", TRUSTSTORE_PATH);
    System.setProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD);
    System.setProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);

    ConnectionConfiguration config = new ConnectionConfiguration(SERVER, 5222);
    config.setSASLAuthenticationEnabled(true);

// config.setSASLAuthenticationEnabled(false);
config.setKeystorePath(KEYSTORE_PATH);
config.setKeystoreType(“jks”);
config.setTruststorePath(TRUSTSTORE_PATH);
config.setTruststorePassword(TRUSTSTORE_PASSWORD);
config.setTruststoreType(“jks”);

    config.setCallbackHandler(new CallbackHandler());

    config.setSecurityMode(SecurityMode.enabled);

// config.setSecurityMode(SecurityMode.required);

    SASLAuthentication.supportSASLMechanism("PLAIN", 0);
    SASLAuthentication.supportSASLMechanism("DIGEST-MD5", 1);
    SASLAuthentication.supportSASLMechanism("EXTERNAL", 2);

// config.setSocketFactory(SSLSocketFactory.getDefault());

    System.out.println("Logging into " + USERNAME + "@" + SERVER);
    try {
        XMPPConnection conn1 = new XMPPConnection(config, new CallbackHandler());
        conn1.connect();
        String usingTLS = (conn1.isUsingTLS() == true) ? "" : " *NOT* ";
        String secure = (conn1.isSecureConnection() == true) ? "" : " *NOT* ";
        System.out.println("Connection is "
            + usingTLS
            + "using TLS and therefore is: "
            + secure
            + "secure.");

Thread.sleep(3 * 1000); // Something about timing in the forums
conn1.login(USERNAME, PASSWORD, “smack test client”);
System.out.println(“Logged " + USERNAME + “@” + SERVER + " in.”);
Thread.sleep(15 * 1000); //leave it connected for a bit, then disconnect.
conn1.disconnect();
System.out.println("Disconnected " + USERNAME + “@” + SERVER);
} catch (XMPPException xe) {
// TODO Auto-generated catch block
xe.printStackTrace();
} catch (InterruptedException ie) {
// TODO Auto-generated catch block
ie.printStackTrace();
}
}

Ive not done any work on Spark/Smack in quite a while, and others have. Its entirely possible the changes others have made broke the callback handling. Ive been pretty busy lately so I dont know if Ill have time to look at it soon either. As far as SSL vs TLS goes, its the same path through the code as far as the SSL negotiation is, so there should be no difference.

The difference between a JKS and a PKCS11 keystore to the client is none, since its using the pure keystore interface. The only real difference is where you get it from.

Sorry Ive not been much help lately, I just have not had the time to work on any of this.

I pulled down SVN an hour ago. I think the problem comes in around here:

[PacketReader:467]
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(“starttls”)) {
// Confirm the server that we want to use TLS
*I added this—> startTLSRequired = true;
connection.startTLSReceived(startTLSRequired);
}
else if (parser.getName().equals(“required”) && startTLSReceived) {
startTLSRequired = true;
}

I’m betting ‘starttls’ comes in as ‘’ not ‘’ – or some other similar construction that doesn’t kick startTLSRequired ‘high’ before proceeding. Thus TLS never gets initialized. Presumably that’s a bug: either the server isn’t sending the right thing, or the client isn’t implementing spec. `s_client’ tells me that the server isn’t sending anything inside :

[…]

00c0 - 74 72 65 61 6d 3a 66 65-61 74 75 72 65 73 3e 3c tream:features><
00d0 - 73 74 61 72 74 74 6c 73-20 78 6d 6c 6e 73 3d 22 starttls xmlns="
00e0 - 75 72 6e 3a 69 65 74 66-3a 70 61 72 61 6d 73 3a urn:ietf:params:
00f0 - 78 6d 6c 3a 6e 73 3a 78-6d 70 70 2d 74 6c 73 22 xml:ns:xmpp-tls"
0100 - 3e 3c 2f 73 74 61 72 74-74 6c 73 3e 3c 6d 65 63 ><mec

[…]

So, somewhere down the line things were adjusted. In any event, it finally gets into the Callback Code in XMPPConnection! It doesn’t work, but it gets there! For some reason, it’s invoking PasswordCallback#getPassword(); which has nothing to do with the CallbackHandler I set with #setCallbackHandler – is in, my callbackHandler doesn’t get invoked.

And it turns out that’s because… yup; that’s reverse ordered, too:

[XMPPClient:1221]

            ks = KeyStore.getInstance(configuration.getKeystoreType());
             try {
                 ks.load(new FileInputStream(configuration.getKeystorePath()), pcb.getPassword());
                 pcb = new PasswordCallback("Keystore Password: ",false);
                 callbackHandler.handle(new Callback[]{pcb});

reversing the order – so the Callback actually gets called:

                 callbackHandler.handle(new Callback[]{pcb});
                 ks.load(new FileInputStream(configuration.getKeystorePath()), pcb.getPassword());
                 pcb = new PasswordCallback("Keystore Password: ",false);

fires off my CallbackHandler as expected.

I’m going to see if i can build a .jar and push this out into Spark as a replacement smack.jar and see what happens. I’m thinking it’ll go better now, though.

Err, sorry this is the right ordering for the callback. The first shall be last…

smack> svn diff source/org/jivesoftware/smack/XMPPConnection.java
Index: source/org/jivesoftware/smack/XMPPConnection.java

— source/org/jivesoftware/smack/XMPPConnection.java (revision 11005)
+++ source/org/jivesoftware/smack/XMPPConnection.java (working copy)
@@ -1219,9 +1219,9 @@
else {
ks = KeyStore.getInstance(configuration.getKeystoreType());
try {

  •                ks.load(new FileInputStream(configuration.getKeystorePath()), pcb.getPassword());
                   pcb = new PasswordCallback("Keystore Password: ",false);
                   callbackHandler.handle(new Callback[]{pcb});
    
  •                ks.load(new FileInputStream(configuration.getKeystorePath()), pcb.getPassword());
               }
               catch(Exception e) {
                   ks = null;
    

Still no joy with Spark, though. But my Smack client is doing everything right and getting in under TLS on :5222

Logging into tester@localhost:5222
Callbacks: [Ljavax.security.auth.callback.Callback;@1f6f0bf
!!! Callback invoked!!!
Connection is using TLS and therefore is: secure.
Logged tester@localhost in.
Disconnected tester@localhost

Not sure why Spark isn’t doing the right thing with an updated smack.jar.

Some other things I forgot to mention:

o config.setCallbackHandler() doesn’t work; you have to provide it on the connect() for it to work.

So the real patch for XMPPConnection is:

smack> svn diff source/org/jivesoftware/smack/XMPPConnection.java
Index: source/org/jivesoftware/smack/XMPPConnection.java

— source/org/jivesoftware/smack/XMPPConnection.java (revision 11005)
+++ source/org/jivesoftware/smack/XMPPConnection.java (working copy)
@@ -226,7 +226,7 @@
config.setSASLAuthenticationEnabled(true);
config.setDebuggerEnabled(DEBUG_ENABLED);
this.configuration = config;

  •    this.callbackHandler = null;
    
  •    this.callbackHandler = config.getCallbackHandler();
    

    }

    /**
    @@ -240,7 +240,7 @@
    */
    public XMPPConnection(ConnectionConfiguration config) {
    this.configuration = config;

  •    this.callbackHandler = null;
    
  •    this.callbackHandler = config.getCallbackHandler();
    

    }

    /**
    @@ -1219,9 +1219,9 @@
    else {
    ks = KeyStore.getInstance(configuration.getKeystoreType());
    try {

  •                ks.load(new FileInputStream(configuration.getKeystorePath()), pcb.getPassword());
                   pcb = new PasswordCallback("Keystore Password: ",false);
                   callbackHandler.handle(new Callback[]{pcb});
    
  •                ks.load(new FileInputStream(configuration.getKeystorePath()), pcb.getPassword());
               }
               catch(Exception e) {
                   ks = null;
    

And it looks like the CallbackHandler isn’t set right in any event:
[XMPPConnection(Config,CBH)] Callback handler: org.jivesoftware.LoginDialog$LoginPanel[,0,188,244x200,layout=java.awt.GridBagL ayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777217,maximumSize=,minimumS ize=,preferredSize=]

OOOOOOOOOOH. I bet… Yup. That’s pointing to the PasswordCallback/CallbackHandler in the login pane… meaning they’re assuming that the keystore and the account have the same password!

Mmmhmm. That works. Completely invalid assumption, but it works when I make them the same. Of course the other hidden caveat is that they’re looking for key under the alias of the username. I haven’t checked fall-back – i.e., does it try “” then “mykey”, but one might presume. So that’s a reasonable thing to do but setting the passwords the same is probably not. There should be a pop-up dialog… or try the original, then pop-up, would be best.

However, now:

Exception in thread “Thread-1” java.lang.NoSuchMethodError: org.jivesoftware.smack.XMPPConnection.login(Ljava/lang/String;Ljava/lang/String ;Ljava/lang/String;Z)V
at org.jivesoftware.LoginDialog$LoginPanel.login(LoginDialog.java:860)
at org.jivesoftware.LoginDialog$LoginPanel.access$400(LoginDialog.java:200)
at org.jivesoftware.LoginDialog$LoginPanel$1.construct(LoginDialog.java:606)
at org.jivesoftware.spark.util.SwingWorker$2.run(SwingWorker.java:131)
at java.lang.Thread.run(Thread.java:595)

But I presume that’s an SVN vs. RC/Beta-2 versioning thing:


r10846 | gato | 2008-10-24 01:17:50 -0400 (Fri, 24 Oct 2008) | 1 line

Simplified list of #login methods in XMPPConnection.

Once i point #login(String,String,String,boolean) -> #login(String,String,String); it logs in perfectly!

That’s with the latest 2.6.0-beta, not using the provided JRE. With another copy of the stock Spark (I think?), the certificate gets sent without the extra login(S,S,S,b) in there, but it gets “stuck” right here:

01E0: 72 65 73 73 69 6F 6E 3E 3C 61 75 74 68 20 78 6D ression><auth xm
01F0: 6C 6E 73 3D 22 68 74 74 70 3A 2F 2F 6A 61 62 62 lns=“http://jabb
0200: 65 72 2E 6F 72 67 2F 66 65 61 74 75 72 65 73 2F er.org/features/
0210: 69 71 2D 61 75 74 68 22 2F 3E 3C 72 65 67 69 73 iq-auth”/><regis
0220: 74 65 72 20 78 6D 6C 6E 73 3D 22 68 74 74 70 3A ter xmlns=“http:
0230: 2F 2F 6A 61 62 62 65 72 2E 6F 72 67 2F 66 65 61 //jabber.org/fea
0240: 74 75 72 65 73 2F 69 71 2D 72 65 67 69 73 74 65 tures/iq-registe
0250: 72 22 2F 3E 3C 2F 73 74 72 65 61 6D 3A 66 65 61 r”/></stream:fea
0260: 74 75 72 65 73 3E 98 E4 3B 39 92 A1 70 90 38 2D tures>…;9…p.8-
0270: FB 9D 16 18 4B 74 …Kt

and eventually disconnects.


The other change was:

smack> svn diff source/org/jivesoftware/smack/PacketReader.java
Index: source/org/jivesoftware/smack/PacketReader.java

— source/org/jivesoftware/smack/PacketReader.java (revision 11005)
+++ source/org/jivesoftware/smack/PacketReader.java (working copy)
@@ -467,6 +467,7 @@
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(“starttls”)) {
// Confirm the server that we want to use TLS

  •                startTLSRequired = true;
                   connection.startTLSReceived(startTLSRequired);
               }
               else if (parser.getName().equals("required") && startTLSReceived) {
    

which isn’t very robust, but at least it does the right thing.

So the end of the day:

  1. Spark 2.6.0-beta2 – stock – might still be broken, but for some other random reason where the connection hangs (provided JRE?)

  2. After applying the above patches to smack (also attached), and redeploying an updated lib/smack.jar, Spark 2.6.0b2 (1.5 JRE) should work for you provided:

  3. Your keystore’s password has:

a) a key+certificate with an alias the same as the user logging in

b) the password for the keystore and the key are the same,

c) the password you enter to login in the dialog is the same as (3.b).

I think that’s all the non-obvious required conditions – in addition to all of the regular openfire setup, and not to use the RPM, which apparently is broken. I’ve not even thought about looking at the diff between .tar.gz and rpm-based installations.

Can these patches be applied to SVN, please? And maybe a document defining everything put together separate from the forums?

If i get some time – and I don’t think I will – I’ll look into what’s breaking beta2

Thanks!
PacketReader-TLS-patch.diff (684 Bytes)
XMPPConnection-Callback-patch.diff (1369 Bytes)

Well this isn’t the best solution, but at least it’s kind of working.

@slushpupie: Is this Problem scheduled to be fixed?

Daniel

I doubt any of the other people with svn access understand this well enough to fix it (anyone who does dev work in PKI certainly understands how rare it is) and Im stretched a bit thin with other commitments at the moment. So no, its not really in a timeline anywhere. Ill try to get on the community group chat today- perhaps we can all discuss it then.

Thanks slushpuppie. The patches are quite limited, so applying them should be very obvious, I don’t think it’s going to require any PKI-specific knowledge to see, e.g., that you must register the callback handler, before calling it back.

However, I do have more to report: apparently I was mistaken regarding the RPM – you were right, there was no difference.

Apparently the crl and client truststore properties (xmpp.client.certificate.crl and xmpp.socket.ssl.client.truststore) only admit of relative URLs. I.e., “/opt/openfire/resources/security/client.truststore” won’t work… “resources/security/client.truststore” will work. That’s a tidy bit of info. Of course, I could not ever verify until I’d patched my Spark client per the above, but that’s probably a critical piece of information for folks to be aware of. I’ll try to add a note to the other thread where you laid out the basic properties.

Anyway, I’d be happy to file a ticket in JIRA, but it’s not open to the public. Could you at least create a ticket, if you have access? And attach the patches, etc? Oddly, I do see that the RPM-based 3.6.3 server is showing <required=“true”>, so I’m not sure what the deal is there, or if I’m looking in the wrong place.

Okay, im getting closer. Your solution seems to work. The only thing which prevents me from connection to the Server is this error:

2009.05.07 10:30:18 Closing session due to exception: (SOCKET, R: /192.168.0.135:2003, L: /192.168.0.135:5222, S: 0.0.0.0/0.0.0.0:5222)
org.apache.mina.filter.codec.ProtocolDecoderException: java.lang.Exception: Disallowed character (Hexdump: 80 62 01 03 01 00 39 00 00 00 20 00 00 04 01 00 80 00 00 05 00 00 2F 00 00 33 00 00 32 00 00 0A 07 00 C0 00 00 16 00 00 13 00 00 09 06 00 40 00 00 15 00 00 12 00 00 03 02 00 80 00 00 08 00 00 14 00 00 11 4A 02 9C 1A 68 7A 1F 9D 31 7C DC DD 0D FF FF 1E E5 52 5F 47 0A 50 7F 13 E5 60 84 F4 EA 0E 19 52)

This occures while TLS handshaking. i think theres someting wrong with my certificates but i dont know what, any idea? is the character ‘-’ disallowed in certificate names?

Daniel

What’s your value for tls – optional? required? And, you’ve replaced the original smack.jar with the updated one? And your keystore contains a key that matches, username and password, against what the jabber server is expecting? I.e., the alias on a key in the keystore matches your jabber userid, and the password to the keystore, aliased key, and jabber account all match?

TLS is set to required. Keys and aliases are all the same, Ive double checked it.

client.truststore, etc. properties are relative path-based and owned by the openfire daemon user?

if you’re using the default client.truststore, just try removing the properties for that and crl, that seemed to help on mine. Make sure the truststore shows that you’re trusting the right CA.

And that the client’s truststore/keystore has the server’s CA certificate (trusted) in it (and aliased different from ‘mykey’ probably).

And you’re sure you’re using the patched .jar file for smack.jar?

I can’t think of anything else to check, sorry

Yes API is patched but, I’ll check those relativ paths. Im confident, this will work soon. I’ll check the whole stuff again maybe Ive missed something. Thanks for the help anyway.

Daniel

Okay, Im still stuck. Ive created those openssl certificates once again using only letters. Imported them into the keystore and truststore of the client with all the same password. The same on the server side. Smack api is fixed with the diff patches which where posted above and repacked with ant.

Ive tried to connect on port 5222 with config.setSocketFactory(SSLSocketFactory.getDefault()); and without it. In both configurations I get "Closing session due to excpetion"and java.lang.Exception: Disallowed character. Openssl client test says that there still arent any certificates offered.

openssl s_client -prexit -connect localhost:5222
Loading ‘screen’ into random state - done
CONNECTED(00000778)
3440:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:.\ssl\s23_lib.c:188:

no peer certificate available

No client certificate CA names sent

SSL handshake has read 0 bytes and written 124 bytes

New, (NONE), Cipher is (NONE)
Compression: NONE
Expansion: NONE

Is this an indication for this problem?

Port 5223 offers certificates, but im not able to connect.

With config.setSocketFactory(SSLSocketFactory.getDefault()); i get sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target and without it get javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?

Im grateful for any help

EDIT: I found out that, when using config.setSocketFactory(SSLSocketFactory.getDefault()); on port 5223 Smack uses the cacerts keystore in the jre folder. If I add my root certificate into that keystore i get javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: Netscape cert type does not permit use for SSL server.

EDIT2: Ive removed all Netscape comments an attributes from those openssl certificates to fix the “Netscape cert type does not permit use for SSL server” problem, but Im ending up in a “null certificate chain”. So, back to the beginning. Im getting mad

Yes; the default SSL context is to use the system-property-based key/trust stores. Openfire does something different by using specific ssl context, which you can set up per my simple client code.

Null cert chain, i’m pretty confident means that the client is not sending CAs. If you can’t get s_client to show any advertised CAs, it means almost definitely that none are being offered. I think this points to an issue with Openfire finding the client.truststore – to what is your client.truststore property set? And navigation to that path is accessible to the user as whom the openfire service is running, correct?

Client.truststore has default settings, I didnt change them. Im using Windows, so the server is running with my user which is administrator. I think if there would be no access to the client.trusstore, an error would be listed in the debug log.Obviously on Port 5223 my certificates are offered, so I think openfire is able to access the client.truststore.

The CallbackHandler, which you are using in your client code, which package is it from? If I import the class which eclipse proposes to me(javax.security.auth.callback.CallbackHandler). It cant be instantiated because it is an Interface. Did you write a callbackhandler by yourself?

EDIT: Obviousely connection via port 5223 is working. Setting those systems propertys made my day But I want to find out, why there are no certificates offerd on port 5222

Yes, I implemented my own basic callbackhandler. That’s how I was able to see that the CallbackHandler was never being invoked – someone had screwed up the ordering of the callback handling statements in the Smack library. It’s really quite simple, I just created a new class implementing the interface and it was:

public void handle(Callback[] callbacks) throws IOException,
        UnsupportedCallbackException {
    System.err.println("Callbacks: " + callbacks);
    System.err.println("!!!!!!!!!  Callback invoked!!!!!!!!!!!!!");
    if (callbacks != null && callbacks[0] != null) {
        PasswordCallback callback = (PasswordCallback) callbacks[0];
        callback.setPassword("password".toCharArray());
    } else {
        System.err.println("Invalid Callback: callbacks[] as null/empty.");
    }
    return;
}

When I never saw the “Callback invoked” line, I knew something was messed up.

As far as why no CA certs are shown on :5222, I think it’s because of how the TLS negotiation works. I don’t see any either. However, it still works to require a valid client certificate. I think there’s some issue with the ‘required=“true”’ being set properly, although it’s possible that on those tests I never set tls.required… can’t be sure… too many tries at it. In any event, it doesn’t appear that Smack will speak TLS if it’s not required, which isn’t wrong, IMO – but I’ve not read the spec. I think if it supports it, and the server supports it, it should be negotiated. My patch just sets TLS if it sees a starttls tag, required or not – not perfect, but it gets the job done, and I’m not familiar enough with the code to fix it The Right Way [tm].

But you’re saying it’s working for you on :5223? It’s probably working on :5222, as long as you have the TLS patch in place, too.

Hm, TLS isnt working, your patch is n place. Ive implemented a callbackhandler but the error occurs befor the callbackhandler gets invoked. Its still “the disallowed character” exception on server side. Anyway its working with SSL. Which Version of SSL does smack/openfire implement? 3.0?

What is Spark’s debug telling you in Raw Sent/Received Packets?