@@ -16,6 +16,9 @@ import (
1616 "fmt"
1717 "io"
1818 "math"
19+ "os"
20+ "path"
21+ "runtime"
1922 "time"
2023)
2124
@@ -219,6 +222,7 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
219222 clientTransactions |
220223 clientLocalFiles |
221224 clientPluginAuth |
225+ clientConnectAttrs |
222226 mc .flags & clientLongFlag
223227
224228 if mc .cfg .clientFoundRows {
@@ -233,7 +237,23 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
233237 // User Password
234238 scrambleBuff := scramblePassword (cipher , []byte (mc .cfg .passwd ))
235239
240+ attrs := map [string ]string {
241+ "_os" : runtime .GOOS ,
242+ "_client_name" : "Go-MySQL-Driver" ,
243+ "_pid" : pid ,
244+ "_platform" : runtime .GOARCH ,
245+ "program_name" : path .Base (os .Args [0 ]),
246+ }
247+
248+ attrlen := 0
249+ for attrname , attrvalue := range attrs {
250+ attrlen += len (attrname ) + len (attrvalue )
251+ // one byte to store attrname length and one byte to store attrvalue length
252+ attrlen += 2
253+ }
254+
236255 pktLen := 4 + 4 + 1 + 23 + len (mc .cfg .user ) + 1 + 1 + len (scrambleBuff ) + 21 + 1
256+ pktLen += attrlen + 1 // one byte to store the total length of attrs
237257
238258 // To specify a db name
239259 if n := len (mc .cfg .dbname ); n > 0 {
@@ -305,6 +325,19 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
305325 // Assume native client during response
306326 pos += copy (data [pos :], "mysql_native_password" )
307327 data [pos ] = 0x00
328+ pos ++
329+
330+ // Connection attributes
331+ data [pos ] = byte (attrlen )
332+ pos ++
333+
334+ for attrname , attrvalue := range attrs {
335+ data [pos ] = byte (len (attrname ))
336+ pos += 1 + copy (data [pos + 1 :], attrname )
337+
338+ data [pos ] = byte (len (attrvalue ))
339+ pos += 1 + copy (data [pos + 1 :], attrvalue )
340+ }
308341
309342 // Send Auth packet
310343 return mc .writePacket (data )
0 commit comments